Помощь в отладке OpenGL glsl Shader или кода с его помощью - PullRequest
1 голос
/ 21 января 2012

Я работаю над добавлением phong shader в мою рабочую программу. По сути, после того, как я реализовал свои новые шейдеры, мой код получает «Ошибка сегментации: 11» во время:

glDrawArrays(GL_TRIANGLES, 0, mCubes.getArrayNumberOfElements());

Я знаю, что количество элементов правильное, потому что оно работало для моего предыдущего простого шейдера.

Вот мой вершинный шейдер:

// vertex shader
attribute vec4 vPosition;
attribute vec3 vNormal;
varying vec4 color; //vertex shader
// light and material properties
uniform vec4 AmbientProduct, DiffuseProduct, SpecularProduct; 
uniform mat4 ModelView;
//uniform mat4 Projection;
uniform vec4 LightPosition;
uniform float Shininess;
vec3 L, H, N, pos, E;
vec4 diffuse, specular, ambient;
float Kd, Ks;

void main()
{
// Transform vertex position into eye coordinates 
pos = (ModelView * vPosition).xyz; 
L = normalize( LightPosition.xyz - pos ); 
E = normalize( -pos );
H = normalize( L + E );
// Transform vertex normal into eye coordinates
N = normalize( ModelView*vec4(vNormal, 0.0) ).xyz;
// Compute terms in the illumination equation 
ambient = AmbientProduct;
Kd = max( dot(L, N), 0.0 );
diffuse = Kd*DiffuseProduct;
Ks = pow( max(dot(N, H), 0.0), Shininess );
specular = Ks * SpecularProduct;
if( dot(L, N) < 0.0 ) 
specular = vec4(0.0, 0.0, 0.0, 1.0); 

gl_Position = ModelView * vPosition;
color = ambient + diffuse + specular;
color.a = 1.0; 
        }

Вот моя функция отображения, в которой код в конечном итоге получает ошибку:

void display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

vector<float> cell = mCubes.getCell();

mat4 matrix = rot * scale(1.0/cell[0], 1.0/cell[1], 1.0/cell[2]) * translate(-cell[0]/2.0, -cell[1]/2.0, -cell[2]/2.0);
glUniformMatrix4fv(vShaderModelView, 1, GL_TRUE, matrix);

glDrawArrays(GL_TRIANGLES, 0, mCubes.getArrayNumberOfElements());


glutSwapBuffers();
glFlush();
}

А вот моя функция инициализации, которая в основном настраивается и взаимодействует с шейдерами:

void init() {
// Create a vertex array object
GLuint vao;
#ifdef __APPLE__
glGenVertexArraysAPPLE( 1, &vao );
glBindVertexArrayAPPLE( vao );
#else
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
#endif

// Create and initialize a buffer object
GLuint buffer;

glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData( GL_ARRAY_BUFFER,
             mCubes.getDisplayArraySize() + mCubes.getDisplayArraySize()*3,                NULL, GL_STATIC_DRAW );
GLintptr offset = 0;
glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getDisplayArraySize(), mCubes.getDisplayArray());
offset+= mCubes.getDisplayArraySize();

glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getDisplayArraySize(), mCubes.getNormalVector());

// Load shaders and use the resulting shader program
string evname = "PROTCAD3DIR";
string path = PCGeneralIO::getEnvironmentVariable(evname);

path += "/data/shaders/";
#ifdef __APPLE__
string vshadername = path + "kw_vshader1_mac.glsl";
string fshadername = path + "kw_fshader1_mac.glsl";
//#else
//  string vshadername = path + "kw_vshader1.glsl";
//  string fshadername = path + "kw_fshader1.glsl";
#endif

GLuint program = InitShader( vshadername.c_str(), fshadername.c_str() );

glUseProgram(program);
// Initialize the vertex position attribute from the vertex shader    
GLuint vShaderPosition = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(vShaderPosition);
glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

GLuint vShaderNormal = glGetAttribLocation(program, "vNormal");
glEnableVertexAttribArray(vShaderNormal);
//glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset)); //this was the ORIGINAL PROBLEM, now commented out and below is solution
  glVertexAttribPointer(vShaderNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));


vShaderModelView = glGetUniformLocation(program, "ModelView");
vShaderLightPosition = glGetUniformLocation(program, "LightPosition");

vShaderAmbientProduct = glGetUniformLocation(program, "AmbientProduct");
vShaderDiffuseProduct = glGetUniformLocation(program, "DiffuseProduct");
vShaderSpecularProduct = glGetUniformLocation(program, "SpecularProduct");
vShaderShininess = glGetUniformLocation(program, "SpecularProduct");
glEnable( GL_DEPTH_TEST );

vec4 light = vec4(0.5,1.5,1.0,0.0);
glUniform4fv(vShaderLightPosition, 1, light);
vec4 amb = vec4(1.0f,0.0f,0.20f,1.0f);
glUniform4fv(vShaderAmbientProduct, 1, amb);
vec4 diff = vec4(0.5f,0.5f,0.5f,1.0f);
glUniform4fv(vShaderDiffuseProduct, 1, diff);
vec4 spec = vec4(0.80f,0.80f,0.80f,1.0f);
glUniform4fv(vShaderSpecularProduct, 1, spec);
float shin = 6.0f;
glUniform1f(vShaderShininess,shin);


glClearColor(.2, .2, .2, 1); /* Grey background */
}

Если у вас есть какие-либо вопросы, не стесняйтесь спрашивать, и я уточню. Я чувствую, что либо у вершинного шейдера есть проблема, либо то, как я взаимодействую с шейдером, делает что-то шаткое. Любая помощь или предложения принимаются!

РЕДАКТИРОВАТЬ ::: (код отредактирован для отражения решения) Проблема была во втором:

glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));

который должен был гласить:

glVertexAttribPointer(vShaderNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));

И это была глупая ошибка копирования / вставки. Тем не менее, готовый продукт все еще не выглядит правильно:

! [При вращении 0 кажется, что оно полностью окрашено] [1]

http://i.stack.imgur.com/CKJ3f.png

! [Поворот немного показывает какое-то странное поведение] [2]

http://i.stack.imgur.com/kyRfI.png

! [Еще большее вращение заставляет вас вырывать волосы] [3]

i.stack.imgur.com / lYOzK.png

! [Затем он исчезает, и вы знаете, что я облажался !!] [4]

i.stack.imgur.com / FZcqF.png

Итак, когда вы поворачиваете, цвет искажается и становится белым, черным, с рисунком и все такое, но это, очевидно, неправильно.

Edit ::: Это моя попытка "исправить" проблему передачи неверного количества значений с помощью vNormal:

void init() {
// Create a vertex array object
GLuint vao;
#ifdef __APPLE__
glGenVertexArraysAPPLE( 1, &vao );
glBindVertexArrayAPPLE( vao );
#else
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
#endif

// Create and initialize a buffer object
GLuint buffer;
realVec *normArray = new realVec[mCubes.getNormalArraySize()];//vec4 array compared to vec3 array     
normArray = mCubes.getNormalVector(); // new array of normals

for(int i=0; i<mCubes.getArrayNumberOfElements();i++){
    printf("Normal at %d  is %f \n",i,normArray[i][0]); //to print normals
    printf("Normal at %d  is %f \n",i,normArray[i][1]); //to print normals
    printf("Normal at %d  is %f \n",i,normArray[i][2]); //to print normals
}

glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData( GL_ARRAY_BUFFER,
             mCubes.getDisplayArraySize() + mCubes.getNormalArraySize(),                NULL, GL_STATIC_DRAW ); //Changed size for vec3 array of normals
GLintptr offset = 0;
glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getDisplayArraySize(), mCubes.getDisplayArray());
offset+= mCubes.getDisplayArraySize();

glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getNormalArraySize(), normArray);

// Load shaders and use the resulting shader program
string evname = "PROTCAD3DIR";
string path = PCGeneralIO::getEnvironmentVariable(evname);

path += "/data/shaders/";
#ifdef __APPLE__
string vshadername = path + "kw_vshader1_mac.glsl";
string fshadername = path + "kw_fshader1_mac.glsl";
//#else
//  string vshadername = path + "kw_vshader1.glsl";
//  string fshadername = path + "kw_fshader1.glsl";
#endif

GLuint program = InitShader( vshadername.c_str(), fshadername.c_str() );

glUseProgram(program);
//offset =0;
// Initialize the vertex position attribute from the vertex shader    
GLuint vShaderPosition = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(vShaderPosition);
glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

GLuint vShaderNormal = glGetAttribLocation(program, "vNormal");
glEnableVertexAttribArray(vShaderNormal);
glVertexAttribPointer(vShaderNormal, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));


//vShaderMatrix = glGetUniformLocation(program, "vMatrix");
//vShaderColor = glGetUniformLocation(program, "vColor")
vShaderModelView = glGetUniformLocation(program, "ModelView");
vShaderLightPosition = glGetUniformLocation(program, "LightPosition");
//vShaderProjection = glGetUniformLocation(program, "Projection");

vShaderAmbientProduct = glGetUniformLocation(program, "AmbientProduct");
vShaderDiffuseProduct = glGetUniformLocation(program, "DiffuseProduct");
vShaderSpecularProduct = glGetUniformLocation(program, "SpecularProduct");
vShaderShininess = glGetUniformLocation(program, "SpecularProduct");
glEnable( GL_DEPTH_TEST );

vec4 light = vec4(0.5,1.5,1.0,0.0);
glUniform4fv(vShaderLightPosition, 1, light);
vec4 amb = vec4(1.0f,0.0f,0.20f,1.0f);
glUniform4fv(vShaderAmbientProduct, 1, amb);
vec4 diff = vec4(0.5f,0.5f,0.5f,1.0f);
glUniform4fv(vShaderDiffuseProduct, 1, diff);
vec4 spec = vec4(0.80f,0.80f,0.80f,1.0f);
glUniform4fv(vShaderSpecularProduct, 1, spec);
float shin = 6.0f;
glUniform1f(vShaderShininess,shin);


glClearColor(.2, .2, .2, 1); /* Grey background */
}

Должен ли я изменить свет, окружающие, зеркальные и рассеянные свойства? Я не уверен, в чем проблема.

1 Ответ

0 голосов
/ 21 января 2012

Вы передаете свои атрибутные данные vNormal, используя следующий код

glVertexAttribPointer(vShaderNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));

Это указывает на то, что у вашего обычного компонента 4 , тогда как в вашем вершинном шейдере вы объявляете его как

attribute vec3 vNormal;

Это несоответствие может быть связано с вашей проблемой, если нормали неверно истолкованы.

...