2014-10-02 7 views
-2

Я пытаюсь обнаружить края силуэта и визуализировать некоторые текстуры (зависит от диффузного термина) на этих краях с помощью OpenGL и шейдеров. Я создаю квад, используя геометрический шейдер, а также назначаю здесь координаты текстуры. В шейдере фрагмента я пытаюсь использовать диффузный термин, рассчитанный в вершинном шейдере, для визуализации различных текстур на основе значения diffTerm. В моем коде есть две проблемы.Текстуры не работают (черные текстуры) - OpenGL + GLSL

1) Диффузный член должен отличаться от (-1,1), но он, кажется, застревает в 0, когда я поворачиваю модель, и она достигает отрицательных значений в определенных положениях.

2) Текстуры всегда черные, и я не могу понять, что вызывает эту проблему.

"MeshViewer.cpp" - Основной файл

Mesh* mesh; 
GLuint* texID = new GLuint[5]; 
float rotn_x = 0.0, rotn_y = 0.0, fov; 
GLuint matrixLoc1, matrixLoc2, matrixLoc3,texLoc1, texLoc2, texLoc3, texLoc4, texLoc5; 
float cam_near, cam_far; //Near and far planes of the camera 
const float PI = 3.14159265f; 
glm::mat4 view; //View and projection matrices 

void loadTextures() 
{ 
glGenTextures(5, texID); //Generate 1 texture ID 
glActiveTexture(GL_TEXTURE0); //Texture unit 0 
glBindTexture(GL_TEXTURE_2D, texID[0]); 
loadTGA("Pencil0.tga"); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glActiveTexture(GL_TEXTURE1); //Texture unit 0 
glBindTexture(GL_TEXTURE_2D, texID[1]); 
loadTGA("Pencil1.tga"); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glActiveTexture(GL_TEXTURE2); //Texture unit 0 
glBindTexture(GL_TEXTURE_2D, texID[2]); 
loadTGA("Pencil2.tga"); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glActiveTexture(GL_TEXTURE3); //Texture unit 0 
glBindTexture(GL_TEXTURE_2D, texID[3]); 
loadTGA("Brick.tga"); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 

glActiveTexture(GL_TEXTURE4); //Texture unit 0 
glBindTexture(GL_TEXTURE_2D, texID[4]); 
loadTGA("Brick.tga"); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
} 
void initialise() 
{ 
// --- Mesh object --- 
GLuint lgtLoc; 
mesh = new Mesh(); 
if(!mesh->loadMeshOFF("Camel.off")) cout << "Error reading mesh data file." << endl; 

// --- Camera parameters --- 
float win_width = (mesh->_xmax - mesh->_xmin) * 1.5f; 
float win_height = (mesh->_ymax - mesh->_ymin) * 1.5f; 
if(win_width > win_height) win_height = win_width; //Maintain aspect ratio = 1 
cam_near = 2*(mesh->_zmax) - mesh->_zmin; 
cam_far = 2*(mesh->_zmin) - mesh->_zmax; 
float cam_posx = (mesh->_xmax + mesh->_xmin) * 0.5f; 
float cam_posy = (mesh->_ymax + mesh->_ymin) * 0.5f; 
float cam_posz = cam_near + win_height; 
fov = 27.0f;        //Approx. atan(0.5) 

// --- Uniform locations --- 
GLuint program = createShaderProg("MeshViewer.vert", "MeshViewer.frag", "MeshViewer.geom"); 
matrixLoc1 = glGetUniformLocation(program, "mvMatrix"); 
matrixLoc2 = glGetUniformLocation(program, "mvpMatrix"); 
matrixLoc3 = glGetUniformLocation(program, "norMatrix"); 
lgtLoc = glGetUniformLocation(program, "lightPos"); 

GLint lineWidth = glGetUniformLocation(program, "HalfWidth"); 
if (lineWidth > -1) 
    glUniform1f(lineWidth, 0.005f); 
GLint overhangLength = glGetUniformLocation(program, "OverhangLength"); 
if (overhangLength > -1) 
    glUniform1f(overhangLength, 0.15f); 

texLoc1 = glGetUniformLocation (program, "tex1"); 
glUniform1i(texLoc1, 0); 
texLoc2 = glGetUniformLocation (program, "tex2"); 
glUniform1i(texLoc2, 1); 
texLoc3 = glGetUniformLocation (program, "tex3"); 
glUniform1i(texLoc3, 2); 
texLoc4 = glGetUniformLocation (program, "tex4"); 
glUniform1i(texLoc4, 3); 
texLoc5 = glGetUniformLocation (program, "tex5"); 
glUniform1i(texLoc5, 4); 


view = glm::lookAt(glm::vec3(cam_posx, cam_posy, cam_posz), glm::vec3(cam_posx, cam_posy, 0.0),   glm::vec3(0.0, 1.0, 0.0)); //view matrix 
glm::vec4 light = glm::vec4(100.0, 50.0, 100.0, 1.0);    //Light's position 
glm::vec4 lightEye = view*light;  //Light position in eye coordinates 
glUniform4fv(lgtLoc, 1, &lightEye[0]); 

// --- OpenGL --- 
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);  
glEnable(GL_DEPTH_TEST); 

glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //Wireframe 
mesh->setColor(0, 0, 1);     //Mesh color = blue. 

mesh->createVAO(); //Create buffer objects for the mesh 
} 


void display() 
{ 
glm::mat4 proj; 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glm::mat4 matrix = glm::mat4(1.0); 
matrix = glm::rotate(matrix, rotn_x, glm::vec3(1.0, 0.0, 0.0)); //rotation about x 
matrix = glm::rotate(matrix, rotn_y, glm::vec3(0.0, 1.0, 0.0)); //rotation about y 
glm::mat4 prodMatrix1 = view*matrix;  //Model-view matrix 
proj = glm::perspective(fov, 1.0f, cam_near, cam_far); //perspective projection matrix 
glm::mat4 prodMatrix2 = proj*prodMatrix1; //The model-view-projection transformation 
glm::mat4 invMatrix = glm::inverse(prodMatrix1); //Inverse of model-view matrix for normal transformation 
glUniformMatrix4fv(matrixLoc1, 1, GL_FALSE, &prodMatrix1[0][0]); 
glUniformMatrix4fv(matrixLoc2, 1, GL_FALSE, &prodMatrix2[0][0]); 
glUniformMatrix4fv(matrixLoc3, 1, GL_TRUE, &invMatrix[0][0]); //Use transpose matrix here 

mesh->render(); 

glFlush(); 
} 


void specialKeys(int key, int x, int y) 
{ 
if(key == GLUT_KEY_LEFT) rotn_y -= 5.0; 
else if(key == GLUT_KEY_RIGHT) rotn_y += 5.0; 
else if(key == GLUT_KEY_UP) rotn_x -= 5.0; 
else if(key == GLUT_KEY_DOWN) rotn_x += 5.0; 
else if(key == GLUT_KEY_PAGE_UP) fov --; 
else if(key == GLUT_KEY_PAGE_DOWN) fov ++; 
if(fov < 1.0) fov = 1.0; 
else if(fov > 80.0) fov = 80.0; 
glutPostRedisplay(); 
} 


int main(int argc, char** argv) 
{ 
glutInit(&argc, argv); 
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 
glutInitWindowSize (600, 600); 
glutInitWindowPosition (20, 10); 
glutCreateWindow ("Mesh Viewer"); 
glutInitContextVersion (4, 2); 
glutInitContextProfile (GLUT_CORE_PROFILE); 

if(glewInit() == GLEW_OK) 
{ 
    cout << "GLEW initialization successful! " << endl; 
    cout << " Using GLEW version " << glewGetString(GLEW_VERSION) << endl; 
} 
else 
{ 
    cerr << "Unable to initialize GLEW ...exiting." << endl; 
    exit(EXIT_FAILURE); 
} 
initialise(); 
glutDisplayFunc(display); 
glutSpecialFunc(specialKeys); 
glutMainLoop(); 
return 0; 
} 

Vertex Shader:

#version 330 

layout (location = 0) in vec4 position; 
layout (location = 1) in vec3 normal; 
layout (location = 2) in vec3 cols; 
layout (location = 3) in vec2 texC; 

uniform mat4 mvMatrix; 
uniform mat4 mvpMatrix; 
uniform mat4 norMatrix; 
uniform vec4 lightPos; 
out float diffTerm; 
out vec4 vColour; 
out float viewTerm; 
out float silhoutte; 
out vec2 TexC; 

void main() 
{ 
vec4 grey = vec4(0.2, 0.2, 0.2, 1.0); 
vec4 posnEye = mvMatrix * position; 
vec4 normalEye = norMatrix * vec4(normal, 0); 
vec4 lgtVec = normalize(lightPos - posnEye); 
vec4 viewVec = normalize(vec4(-posnEye.xyz, 0)); 
float viewTerm = max(dot(viewVec, normalEye),0); 
vec4 material = vec4(cols, 1.0); 
vec4 lgtAmb = grey * material; 
diffTerm = max(dot(lgtVec, normalEye), 0); 
vec4 lgtDiff = material * diffTerm; 
silhoutte = dot(viewVec, normalEye); 
gl_Position = mvpMatrix * position; 
vColour = vec4(cols, 1); 
TexC = texC; 
} 

Geometry Shader:

#version 430 core 


layout(triangles_adjacency) in; 
layout(triangle_strip, max_vertices = 6) out; 
in vec2 texC[]; 
out vec2 TexCoord; 
in vec4 vColour[]; 
out vec4 colorv; 
in float viewTerm[]; 
out float viewTermg; 
in float diffTerm[]; 
out float diffTermg; 
in vec2 TexC[]; 
out vec2 TexCg; 
uniform float HalfWidth; 
uniform float OverhangLength; 
out float gDist; 
out vec3 gSpine; 

bool IsFront(vec3 A, vec3 B, vec3 C) 
{ 
float area = (A.x * B.y - B.x * A.y) + (B.x * C.y - C.x * B.y) + (C.x * A.y - A.x * C.y); 
return area > 0; 
} 

void EmitEdge(vec3 P0, vec3 P1) 
{ 
vec3 E = OverhangLength * vec3(P1.xy - P0.xy, 0); 
vec2 V = normalize(E.xy); 
vec3 N = vec3(-V.y, V.x, 0) * 0.005; 
vec3 S = -N; 
float D = HalfWidth; 

gSpine = P0; 
gl_Position = vec4(P0 + S - E, 1); gDist = +D; TexCoord=vec2(0.0,0.0); colorv = vColour[0];  EmitVertex(); 
gl_Position = vec4(P0 + N - E, 1); gDist = -D; TexCoord=vec2(1.0,0.0); colorv = vColour[1]; EmitVertex(); 
gSpine = P1; 
gl_Position = vec4(P1 + S + E, 1); gDist = +D; TexCoord=vec2(1.0,1.0); colorv = vColour[0]; EmitVertex(); 
gl_Position = vec4(P1 + N + E, 1); gDist = -D; ; TexCoord=vec2(0.0,1.0); EmitVertex(); 
EndPrimitive(); 
} 

void main() 
{ 
vec3 v0 = gl_in[0].gl_Position.xyz/gl_in[0].gl_Position.w; 
vec3 v1 = gl_in[1].gl_Position.xyz/gl_in[1].gl_Position.w; 
vec3 v2 = gl_in[2].gl_Position.xyz/gl_in[2].gl_Position.w; 
vec3 v3 = gl_in[3].gl_Position.xyz/gl_in[3].gl_Position.w; 
vec3 v4 = gl_in[4].gl_Position.xyz/gl_in[4].gl_Position.w; 
vec3 v5 = gl_in[5].gl_Position.xyz/gl_in[5].gl_Position.w; 

if (IsFront(v0, v2, v4)) { 
    if (!IsFront(v0, v1, v2)) EmitEdge(v0, v2); 
    //if (!IsFront(v2, v3, v4)) EmitEdge(v2, v4); 
    //if (!IsFront(v0, v4, v5)) EmitEdge(v4, v0); 
} 

} 

Фрагмент Shader:

#version 330 

in vec4 vColourg; 
in float diffTermg; 
in float silhoutte; 
in vec2 TexCg; 
in vec2 TexCoord; 
uniform sampler2D tex1; 
uniform sampler2D tex2; 
uniform sampler2D tex3; 
uniform sampler2D tex4; 
uniform sampler2D tex5; 

void main() 
{ 



vec4 texColor1 = texture(tex1, TexCoord); 
vec4 texColor2 = texture(tex2, TexCoord); 
vec4 texColor3 = texture(tex3, TexCoord); 
vec4 texColor4 = texture(tex4, TexCoord); 
vec4 texColor5 = texture(tex5, TexCoord); 

vec4 blue = vec4(0.0,0.0,1.0,0.0); 
vec4 red = vec4(1.0,0.0,0.0,0.0); 
vec4 yellow = vec4(1.0,1.0,0.0,0.0); 


if (diffTermg<0) 
{ 
gl_FragColor = blue; 
} 
else if (diffTermg ==0) 
{ 
gl_FragColor = texColor5; 
} 
else if (diffTermg > 0 && diffTermg < 0.2) 
gl_FragColor = yellow; 
else if (diffTermg > 100) 
gl_FragColor = blue; 

} 

EDIT: Shader.h

GLuint loadShader(GLenum shaderType, string filename) 
{ 
ifstream shaderFile(filename.c_str()); 
if(!shaderFile.good()) cout << "Error opening shader file." << endl; 
stringstream shaderData; 
shaderData << shaderFile.rdbuf(); 
shaderFile.close(); 
string shaderStr = shaderData.str(); 
const char* shaderTxt = shaderStr.c_str(); 

GLuint shader = glCreateShader(shaderType); 
glShaderSource(shader, 1, &shaderTxt, NULL); 
glCompileShader(shader); 
GLint status; 
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); 
if (status == GL_FALSE) 
{ 
    GLint infoLogLength; 
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); 
    GLchar *strInfoLog = new GLchar[infoLogLength + 1]; 
    glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog); 
    const char *strShaderType = NULL; 
    cerr << "Compile failure in shader: " << strInfoLog << endl; 
    delete[] strInfoLog; 
} 
return shader; 
} 

GLuint createShaderProg(string vertShader, string fragShader, string geomShader) 
{ 
GLuint shaderv = loadShader(GL_VERTEX_SHADER, vertShader); 
GLuint shaderf = loadShader(GL_FRAGMENT_SHADER, fragShader); 
GLuint shaderg = loadShader(GL_GEOMETRY_SHADER, geomShader); 

GLuint program = glCreateProgram(); 
glAttachShader(program, shaderv); 
glAttachShader(program, shaderf); 
glAttachShader(program, shaderg); 
glLinkProgram(program); 

GLint status; 
glGetProgramiv (program, GL_LINK_STATUS, &status); 
if (status == GL_FALSE) 
{ 
    GLint infoLogLength; 
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); 
    GLchar *strInfoLog = new GLchar[infoLogLength + 1]; 
    glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog); 
    fprintf(stderr, "Linker failure: %s\n", strInfoLog); 
    delete[] strInfoLog; 
    program = 0; 
} 
glUseProgram(program); 
return program; 
} 

loadTGA.h

void loadTGA(string filename) 
{ 
char id, cmap, imgtype, bpp, c_garb; 
char* imageData, temp; 
short int s_garb, wid, hgt; 
int nbytes, size, indx; 
ifstream file(filename.c_str(), ios::in | ios::binary); 
if(!file) 
{ 
    cout << "*** Error opening image file: " << filename.c_str() << endl; 
    exit(1); 
} 
file.read (&id, 1); 
file.read (&cmap, 1); 
file.read (&imgtype, 1);  
if(imgtype != 2 && imgtype != 3) //2= colour (uncompressed), 3 = greyscale (uncompressed) 
{ 
    cout << "*** Incompatible image type: " << (int)imgtype << endl; 
    exit(1); 
} 
//Color map specification 
file.read ((char*)&s_garb, 2); 
file.read ((char*)&s_garb, 2); 
file.read (&c_garb, 1); 
//Image specification 
file.read ((char*)&s_garb, 2); //x origin 
file.read ((char*)&s_garb, 2); //y origin 
file.read ((char*)&wid, 2);  //image width         
file.read ((char*)&hgt, 2);  //image height 
file.read (&bpp, 1);  //bits per pixel 
file.read (&c_garb, 1); //img descriptor 
nbytes = bpp/8;   //No. of bytes per pixels 
size = wid * hgt * nbytes; //Total number of bytes to be read 
imageData = new char[size]; 
file.read(imageData, size); 
//cout << ">>>" << nbytes << " " << wid << " " << hgt << endl; 
if(nbytes > 2) //swap R and B 
{ 
    for(int i = 0; i < wid*hgt; i++) 
    { 
     indx = i*nbytes; 
     temp = imageData[indx]; 
     imageData[indx] = imageData[indx+2]; 
     imageData[indx+2] = temp; 
    } 
} 

switch (nbytes) 
{ 
    case 1: 
     glTexImage2D(GL_TEXTURE_2D, 0, 1, wid, hgt, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, imageData); 
     break; 
    case 3: 
     glTexImage2D(GL_TEXTURE_2D, 0, 3, wid, hgt, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData); 
     break; 
    case 4: 
     glTexImage2D(GL_TEXTURE_2D, 0, 4, wid, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); 
     break; 
} 
delete imageData;      
} 
+0

Где вы активируете свою шейдерную программу (например, glUseProgram())? –

+0

@AntonAngelov: я добавил файл заголовка, который выполняет загрузку шейдеров. Он содержит glUseProgram(). – Ravi

+2

Я не вижу, где вы загружаете свои текстуры, но я предполагаю, что вы делаете это правильно. Просто идея, вы можете установить цвет фейдера-шейдера, чтобы показать УФ-координаты (просто вы можете узнать, возникает ли проблема из текстуры или коордов). Другое дело: если диффузный термин застрял в 0, означает, что либо ваш вектор света, либо нормальный вектор неверен. "vec4 lgtVec = normalize (lightPos - posnEye);" Здесь ваш светлый вектор указывает от LightPos (возможно, worldspace) на Vertex (пространство камеры), а диффузный термин Ламберта требует, чтобы L был обратным вектором (от вершины к источнику света [в том же пространстве]). Просто мысль. –

ответ

1

Вы запрашиваете контекст ядра профиля:

glutInitContextProfile(GLUT_CORE_PROFILE); 

Но ваши glTexImage2D() звонки не совместимы с основным профилем:

glTexImage2D(GL_TEXTURE_2D, 0, 1, wid, hgt, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, imageData); 
glTexImage2D(GL_TEXTURE_2D, 0, 3, wid, hgt, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData); 
glTexImage2D(GL_TEXTURE_2D, 0, 4, wid, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); 

Использование количества компонентов в качестве внутреннего формата (аргумент 3) является устаревшим из OpenGL 1.0 и, наконец, устранено при вводе основного профиля. GL_LUMINANCE также ушел. Современный (основной профиль) эквивалент этих вызовов:

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, wid, hgt, 0, GL_RED, GL_UNSIGNED_BYTE, imageData); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, wid, hgt, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, wid, hgt, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); 

сообщения содержит много кода, и я не изучал подробно, чтобы увидеть, если есть и другие проблемы. Я настоятельно рекомендую использовать glGetError(), в котором сообщалось бы об этих недопустимых аргументах, а также было бы полезно проверить, есть ли какие-либо дополнительные проблемы.

Смежные вопросы