เปลี่ยนโฟลตในจุดยอดเชเดอร์ (GLSL)

ฉันคิดว่ามันใช้งานได้แล้ว แต่ยังไม่ทราบวิธีเปลี่ยนค่าในจุดยอดเชเดอร์ของฉัน สิ่งที่ฉันทำใน opengl มีดังต่อไปนี้สำหรับการเรนเดอร์แต่ละครั้ง:

//i bind my shader
shader.bind();

// Then trying to set the value in my vertex shader like so:
GLuint test = glGetUniformLocation(shader.id(), "Test");
glUniform1f(test, 6.0f);

// Do some other stuff like rendering an object
// ...

// then unbind shader
shader.unbind();

นี่คือค่าที่ฉันต้องการเปลี่ยนในจุดยอดของฉัน:

uniform float Test = 0.66; // Doesn't work
//const float Test = 0.66; // Works

แต่เชเดอร์ของฉันไม่ทำงานเมื่อฉันลอง มันทำให้วัตถุของฉันเป็นสีดำ

ถ้าฉันแสดงความคิดเห็นส่วน glGetUniform(Location) ออกและหากใช้ float เป็น const แทนที่จะเป็น < strong>สม่ำเสมอ จากนั้นเชดเดอร์ของฉันก็ทำงานได้ดี แต่ฉันต้องการที่จะเปลี่ยนค่าในเชเดอร์ของฉันในการเรนเดอร์แต่ละครั้ง ฉันว่าฉันต้องใช้เครื่องแบบเพื่อสิ่งนั้น...?

มีบางอย่างที่ฉันขาดหายไป..??


แก้ไข:

ดูเหมือนว่าฉันได้รับข้อผิดพลาด GLSL ต่อไปนี้:

การแสดงออกที่ไม่คงที่ในการเริ่มต้น

ดังนั้นจึงต้องคงที่จึงจะทำงานได้... นั่นหมายความว่าไม่มีทางที่จะให้สิ่งนี้เป็นค่าไดนามิก..?

นี่คือ Vertex Shader ของฉัน:

const float FresnelPower = 1.0;
uniform float Eta;         // <---- MUST BE CONSTANT...

const float F  = ((1.0-Eta) * (1.0-Eta)) / ((1.0+Eta) * (1.0+Eta));

varying vec3  Reflect;
varying vec3  Refract;
varying float Ratio;

void main()
{
    vec4 ecPosition  = gl_ModelViewMatrix * gl_Vertex;
    vec3 ecPosition3 = ecPosition.xyz / ecPosition.w;

    vec3 i = normalize(ecPosition3);
    vec3 n = normalize(gl_NormalMatrix * gl_Normal);

    Ratio   = F + (1.0 - F) * pow((1.0 - dot(-i, n)), FresnelPower);

    Refract = refract(i, n, Eta);
    Refract = vec3(gl_TextureMatrix[0] * vec4(Refract, 1.0));

    Reflect = reflect(i, n);
    Reflect = vec3(gl_TextureMatrix[0] * vec4(Reflect, 1.0));

    gl_Position = ftransform();
}

person w00    schedule 28.01.2012    source แหล่งที่มา


คำตอบ (2)


คุณต้องประกาศเครื่องแบบของคุณในเชดเดอร์จุดสุดยอดดังนี้:

uniform float Test;

นอกจากนี้ คุณต้องเรียก glUseProgram() ด้วยตัวจัดการอ็อบเจ็กต์โปรแกรมของคุณก่อนที่จะเรียก glUniform1f() ดังนั้นตรวจสอบให้แน่ใจว่านั่นคือสิ่งที่ shader.bind() ของคุณทำ เพียงพอแล้วหากคุณโทร glGetUniformLocation() หนึ่งครั้งและแคชผลลัพธ์ นอกจากนี้ ให้ตรวจสอบข้อผิดพลาดของการเรียก OpenGL ของคุณด้วย glGetError() เพื่อให้แน่ใจว่าทุกอย่างทำงานได้อย่างถูกต้อง

ตอบกลับการแก้ไขของคุณ ฉันคิดว่าบรรทัดนี้เป็นปัญหาของคุณ:

const float F  = ((1.0-Eta) * (1.0-Eta)) / ((1.0+Eta) * (1.0+Eta));

const หมายถึงค่าคงที่ของเวลาคอมไพล์ เช่นเดียวกับค่าที่ไม่สามารถเปลี่ยนแปลงได้ด้วยเครื่องแบบ F ไม่สามารถเป็นค่าคงที่ได้ เนื่องจากตัวแปรแบบสม่ำเสมอไม่ใช่ค่าคงที่ (เวลาคอมไพล์) ย้ายบรรทัดที่ประกาศ F ไปที่เนื้อหาของ main และลบตัวระบุ const จากนั้นเชเดอร์ของคุณควรใช้งานได้

person Antti    schedule 28.01.2012
comment
ฉันลองสิ่งที่คุณพูดแล้ว ตรวจสอบด้วย glGetError() และมันทำให้ฉันมีข้อผิดพลาดเมื่อฉันพยายามผูกเชเดอร์ (glUserProgram) ฉันแก้ไขจุดบกพร่องเพิ่มเติมอีกเล็กน้อยและสังเกตเห็นว่าฉันมีข้อผิดพลาดในการคอมไพล์ glsl ฉันได้แก้ไขโพสต์แรกของฉันพร้อมรายละเอียดเพิ่มเติม บางทีคุณอาจรู้คำตอบสำหรับเรื่องนั้น? - person w00; 28.01.2012

uniform float Eta;         // <---- MUST BE CONSTANT...

เมื่อ GLSL พูดว่า "คงที่" ความหมายคือค่าคงที่ เวลาคอมไพล์ ค่าของ Eta มีความสม่ำเสมอในการเรียกเสมอๆ แต่มันไม่คงที่ เพราะมันสามารถเปลี่ยน ระหว่าง ดึงสายได้ คอมไพเลอร์ไม่ทราบว่าค่านี้จะเป็นเท่าใดในเวลาคอมไพล์

ตัวแปร const คือค่าคงที่ เวลาคอมไพล์ ดังนั้นจึงต้องเริ่มต้นด้วยนิพจน์ที่ประกอบด้วยค่าคงที่เวลาคอมไพล์เท่านั้น uniforms ไม่ใช่ค่าคงที่เวลาคอมไพล์ ดังนั้นคุณจึงไม่สามารถเริ่มต้นตัวแปร const ด้วยค่าเหล่านี้ได้

person Nicol Bolas    schedule 28.01.2012