我的程序一直運行良好,但事實證明我很幸運。我開始做着色器的一些清理工作,因爲它充滿了實驗性的東西,我在片段着色器的結尾以下行:紋理顯示爲純黑色,除非我將無效值傳遞到紋理統一位置
gl_FragColor = final_color * (texture2D(tex, gl_TexCoord[0].st)*1.0 + texture2D(tex2, gl_TexCoord[0].st)*1.0);
我試圖把它清理乾淨,我有以下聲明在頂部:
uniform sampler2D tex, tex2;
這些行改爲:
gl_FragColor = final_color * texture2D(tex, gl_TexCoord[0].st;
和
uniform sampler2D tex;
實際上打破了計劃(黑屏),即使我在我的主代碼做
GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex");
glUniform1i(tex_loc, texture_id_);
。我確定這是一個紋理問題,而不是glsl編譯器錯誤,因爲我可以將1.0
添加到輸出中,並以網格的白色輪廓結束。
gl_FragColor = final_color * texture2D(tex2, gl_TexCoord[0].st;
和
uniform sampler2D tex2;
但仍檢索位置tex
:
陌生感當我改變了線我着色器開始。儘管在調試器中檢查tex_loc
的值表明存在錯誤,但程序仍然像以往一樣工作。我不喜歡這樣做,現在我正試圖加載多個紋理,它會導致更大的麻煩。
我使用交織格式的VBO來渲染幾何。我以這種方式傳遞頂點位置,正常和texcoord。
「黑色紋理」問題還有其他問題,但他們使用即時模式調用並設置錯誤的紋理狀態。我在提供數組之前嘗試更改紋理單元,但沒有成功。
這裏是主程序儘可能多的相關代碼可能:
void MeshWidget::draw() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -4.0f + zoom_factor_);
glRotatef(rotX, 1.0f, 0.0f, 0.0f);
glRotatef(rotY, 0.0f, 1.0f, 0.0f);
glRotatef(rotZ, 0.0f, 0.0f, 1.0f);
// Auto centre mesh based on vertex bounds.
glTranslatef(-x_mid_, -y_mid_, -z_mid_);
glDrawElements(GL_TRIANGLES, mesh_.num_indices, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); //The starting point of the IBO
}
void MeshWidget::openMesh(const string& filename) {
if (mesh_filename_ != filename) {
clearMeshData(mesh_);
glDeleteBuffersARB(1, &VertexVBOID);
glDeleteBuffersARB(1, &IndexVBOID);
ReadMsh(mesh_, filename);
// Create buffer objects here.
glGenBuffersARB(1, &VertexVBOID);
glBindBufferARB(GL_ARRAY_BUFFER, VertexVBOID);
glBufferDataARB(GL_ARRAY_BUFFER, sizeof(VertexAttributes)*mesh_.num_vertices, &mesh_.vertices[0], GL_STATIC_DRAW);
glGenBuffersARB(1, &IndexVBOID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint16_t)*mesh_.num_indices, &mesh_.indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(12)); //The starting point of normals, 12 bytes away
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(24)); //The starting point of texcoords, 24 bytes away
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID);
if (startup_done_) updateGL();
}
}
void MeshWidget::openTexture(const string& filename) {
size_t dot = filename.find_last_of('.');
string ext(filename, dot, filename.size()); // 3rd parameter should be length of new string, but is internally clipped to end.
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glDeleteTextures(1, &texture_id_);
glGenTextures(1, &texture_id_);
glBindTexture(GL_TEXTURE_2D, texture_id_);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
if (ext == ".dds") {
if (GLEE_EXT_texture_compression_s3tc) {
texture_id_ = SOIL_load_OGL_texture(filename.c_str(), SOIL_LOAD_AUTO, texture_id_, SOIL_FLAG_DDS_LOAD_DIRECT);
// SOIL takes care of calling glTexParams, glTexImage2D, etc.
yflip_texture_ = true;
} else {
//std::cout << "S3TC not supported on this graphics hardware." << std::endl;
// TODO: Error message in status bar?
}
} else {
QImage tex(filename.c_str());
tex = QGLWidget::convertToGLFormat(tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
yflip_texture_ = false;
}
updateUniforms();
if (startup_done_) updateGL();
}
void MeshWidget::updateUniforms() {
GLuint texture_flip_uniform = glGetUniformLocation(shader_prog_id_, "yflip");
glUniform1f(texture_flip_uniform, float(yflip_texture_ * 1.0f));
GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex");
glUniform1i(tex_loc, texture_id_);
}
我的着色器(還是有一些垃圾在這裏,因爲我嘗試,但沒有什麼影響輸出):
varying vec3 normal, lightDir, eyeVec;
uniform float yflip;
void main()
{
normal = gl_NormalMatrix * gl_Normal;
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
lightDir = vec3(gl_LightSource[0].position.xyz - vVertex);
eyeVec = -vVertex;
gl_TexCoord[0].x = gl_MultiTexCoord0.x;
gl_TexCoord[1].x = gl_MultiTexCoord1.x;
if (yflip == 1.0) {
gl_TexCoord[0].y = 1 - gl_MultiTexCoord0.y;
gl_TexCoord[1].y = 1 - gl_MultiTexCoord1.y;
} else {
gl_TexCoord[0].y = gl_MultiTexCoord0.y;
gl_TexCoord[1].y = gl_MultiTexCoord1.y;
}
gl_Position = ftransform();
}
片段着色器:
varying vec3 normal, lightDir, eyeVec;
uniform sampler2D tex2;
void main (void)
{
vec4 texel = texture2D(tex2, gl_TexCoord[0].st);
vec4 final_color =
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) +
(gl_LightSource[0].ambient * gl_FrontMaterial.ambient);
vec3 N = normalize(normal);
vec3 L = normalize(lightDir);
float lambertTerm = dot(N,L);
if(lambertTerm > 0.0)
{
final_color += gl_LightSource[0].diffuse *
gl_FrontMaterial.diffuse *
lambertTerm;
vec3 E = normalize(eyeVec);
vec3 R = reflect(-L, N);
float specular = pow(max(dot(R, E), 0.0),
gl_FrontMaterial.shininess);
final_color += gl_LightSource[0].specular *
gl_FrontMaterial.specular *
specular;
}
gl_FragColor = final_color * texel;
}
只是爲了澄清,你的意思是我應該通過'GL_TEXTURE0'來代替'texture_id_'嗎? – usm
是的。或者,您可以傳遞0,如glActiveTexture鏈接中所述。 – arul
根據我的OpenGL SuperBible副本,它應該是'0',而不是enum中的值,當我剛剛嘗試時它導致崩潰。謝謝! – usm