2012-02-06 17 views
6

Sto provando a usare i buffer uniformi ma non funziona come supposto. Ho due buffer uniformi, uno è l'illuminazione e l'altro è per materiale. Il problema è che i colori non sono quello che dovrebbero essere e cambiano ogni volta che muovo la fotocamera. Questo problema non esisteva quando usavo uniformi normali. Ecco le immagini per mostrare cosa intendo: When using uniform buffers e when using normal uniforms!Buffer OpenGL Uniform?

Questo è il mio frammento di shader:

#version 400 // Fragment Shader 
uniform layout(std140); 

in vec3 EyePosition; 
in vec3 EyeNormal; 
in vec2 TexCoord; 

out vec4 FragColor; 

uniform sampler2D Texture; 

uniform LightBlock 
{ 
    vec4 Position; 
    vec4 Intensity; 
} Light; 

uniform MaterialBlock 
{ 
    vec4 Ambient; 
    vec4 Diffuse; 
} Material; 

vec4 PointLight(in int i, in vec3 ECPosition, in vec3 ECNormal) 
{ 
    vec3 n = normalize(ECNormal); 
    vec3 s = normalize(Light.Position.xyz - ECPosition); 

    return Light.Intensity * (Material.Ambient + Material.Diffuse * max(dot(s, n), 0.0)); 
} 

void main() 
{ 
    FragColor = texture(Texture, TexCoord); 
    FragColor *= PointLight(0, EyePosition, EyeNormal); 
} 

io non sono sicuro che ho fatto tutto giusto, ma ecco come creo i buffer uniformi:

glGenBuffers(1, &light_buffer); 
glGenBuffers(1, &material_buffer); 

glBindBuffer(GL_UNIFORM_BUFFER, light_buffer); 
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), nullptr, GL_DYNAMIC_DRAW); 

glBindBuffer(GL_UNIFORM_BUFFER, material_buffer); 
glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialBlock), nullptr, GL_DYNAMIC_DRAW); 

GLuint program = Shaders.GetProgram(); 

light_index = glGetUniformBlockIndex(program, "LightBlock"); 
material_index = glGetUniformBlockIndex(program, "MaterialBlock"); 

glUniformBlockBinding(program, light_index, 0); 
glUniformBlockBinding(program, material_index, 1); 

glBindBufferBase(GL_UNIFORM_BUFFER, 0, light_buffer); 
glBindBufferBase(GL_UNIFORM_BUFFER, 1, material_buffer); 

EDIT: Ecco come riempio il buffer:

// Global structures 
struct LightBlock 
{ 
    Vector4 Position; // Vector4 is a vector class I made 
    Vector4 Intensity; 
}; 

struct MaterialBlock 
{ 
    Vector4 Ambient; 
    Vector4 Diffuse; 
}; 

// This is called for every object rendered 
LightBlock Light; 
Light.Position = Vector3(0.0f, 5.0f, 5.0f) * Camera.GetCameraMatrix(); 
Light.Intensity = Vector4(1.0f); 

glBindBuffer(GL_UNIFORM_BUFFER, light_buffer); 
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightBlock), &Light); 

MaterialBlock Material; 
Material.Diffuse = Vector4(1.0f); 
Material.Ambient = Material.Diffuse * Vector4(0.3f); 

glBindBuffer(GL_UNIFORM_BUFFER, material_buffer); 
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(MaterialBlock), &Material); 
+0

Che cosa hai fatto per eseguire il debug di questo? Hai provato a stampare quali valori ottieni nello shader (semplicemente scrivendoli come output del framment shader)? Almeno con i colori, dovresti essere in grado di vedere quali valori non vengono fuori come ti aspetti. –

+0

Inoltre, dov'è il codice che si usa per riempire quei buffer con i valori? –

+0

@Gigi: non l'ho visto su Cat 12.1. Sembra funzionare bene per me, e io uso 2 blocchi nel mio shader di frammenti. Inoltre, hai presentato segnalazioni di bug su questo? –

risposta

2

Ho avuto lo stesso problema, ma solo con AMD (non NVIDIA). La cosa divertente è che il problema si è verificato solo cambiando la matrice della vista.

Come ho avuto un problema ripetibile a seconda del cambiamento della matrice vista, sono stato in grado di rintracciare la causa principale (facendo prove ed errori ardui). Quando si modifica la vista nella mia applicazione, alloco e liberare alcune risorse OpenGL in modo dinamico a seconda di cosa è necessario. In questo processo, c'è una chiamata a glDeleteBuffers() per il buffer 0. Se utilizzo un'istruzione condizionale per non chiamare glDeleteBuffers per il buffer 0, il problema scompare.

Secondo la documentazione, il buffer 0 verrà ignorato silenziosamente da glDeleteBuffers. La mia ipotesi è che ci sia un bug nei driver AMD.

1

Provare ad aggiornare il buffer utilizzando glMapBuffer/glUnmapBuffer.