【发布时间】:2014-05-09 02:07:45
【问题描述】:
我正在尝试通过在 OpenGL 3+ 中使用着色器来实现一种简单的投影纹理映射方法。虽然网络上有一些示例,但我在使用着色器创建工作示例时遇到了麻烦。
我实际上计划使用两个着色器,一个用于绘制普通场景,另一个用于投影纹理映射。我有一个绘制场景void ProjTextureMappingScene::renderScene(GLFWwindow *window) 的函数,我正在使用 glUseProgram() 在着色器之间切换。正常绘图工作正常。但是,我不清楚我应该如何在已经纹理化的立方体上渲染投影纹理。我是否必须以某种方式使用模板缓冲区或帧缓冲区对象(场景的其余部分应该不受影响)?
我也不认为我的投影纹理映射着色器是正确的,因为我第二次渲染立方体时它显示为黑色。此外,我尝试使用颜色进行调试,只有着色器的 t 组件似乎非零(因此立方体显示为绿色)。我在下面的片段着色器中覆盖了texColor,只是为了调试。
顶点着色器
#version 330
uniform mat4 TexGenMat;
uniform mat4 InvViewMat;
uniform mat4 P;
uniform mat4 MV;
uniform mat4 N;
layout (location = 0) in vec3 inPosition;
//layout (location = 1) in vec2 inCoord;
layout (location = 2) in vec3 inNormal;
out vec3 vNormal, eyeVec;
out vec2 texCoord;
out vec4 projCoords;
void main()
{
vNormal = (N * vec4(inNormal, 0.0)).xyz;
vec4 posEye = MV * vec4(inPosition, 1.0);
vec4 posWorld = InvViewMat * posEye;
projCoords = TexGenMat * posWorld;
// only needed for specular component
// currently not used
eyeVec = -posEye.xyz;
gl_Position = P * MV * vec4(inPosition, 1.0);
}
片段着色器
#version 330
uniform sampler2D projMap;
uniform sampler2D gSampler;
uniform vec4 vColor;
in vec3 vNormal, lightDir, eyeVec;
//in vec2 texCoord;
in vec4 projCoords;
out vec4 outputColor;
struct DirectionalLight
{
vec3 vColor;
vec3 vDirection;
float fAmbientIntensity;
};
uniform DirectionalLight sunLight;
void main (void)
{
// supress the reverse projection
if (projCoords.q > 0.0)
{
vec2 finalCoords = projCoords.st / projCoords.q;
vec4 vTexColor = texture(gSampler, finalCoords);
// only t has non-zero values..why?
vTexColor = vec4(finalCoords.s, finalCoords.t, finalCoords.r, 1.0);
//vTexColor = vec4(projCoords.s, projCoords.t, projCoords.r, 1.0);
float fDiffuseIntensity = max(0.0, dot(normalize(vNormal), -sunLight.vDirection));
outputColor = vTexColor*vColor*vec4(sunLight.vColor * (sunLight.fAmbientIntensity + fDiffuseIntensity), 1.0);
}
}
TexGen 矩阵的创建
biasMatrix = glm::mat4(0.5f, 0, 0, 0.5f,
0, 0.5f, 0, 0.5f,
0, 0, 0.5f, 0.5f,
0, 0, 0, 1);
// 4:3 perspective with 45 fov
projectorP = glm::perspective(45.0f * zoomFactor, 4.0f / 3.0f, 0.1f, 1000.0f);
projectorOrigin = glm::vec3(-3.0f, 3.0f, 0.0f);
projectorTarget = glm::vec3(0.0f, 0.0f, 0.0f);
projectorV = glm::lookAt(projectorOrigin, // projector origin
projectorTarget, // project on object at origin
glm::vec3(0.0f, 1.0f, 0.0f) // Y axis is up
);
mModel = glm::mat4(1.0f);
...
texGenMatrix = biasMatrix * projectorP * projectorV * mModel;
invViewMatrix = glm::inverse(mModel*mModelView);
再次渲染立方体
我也不清楚立方体的模型视图应该是什么?它应该使用幻灯机的视图矩阵(就像现在一样)还是普通的视图投影仪?目前,立方体在场景视图的中间呈现为黑色(如果调试则为绿色),就像它从幻灯机中显示的那样(我制作了一个切换热键,以便我可以看到幻灯机“看到”的内容)。立方体也随着视图移动。如何将投影投射到立方体本身?
mModel = glm::translate(projectorV, projectorOrigin);
// bind projective texture
tTextures[2].bindTexture();
// set all uniforms
...
// bind VBO data and draw
glBindVertexArray(uiVAOSceneObjects);
glDrawArrays(GL_TRIANGLES, 6, 36);
在主场景相机和幻灯机相机之间切换
if (useMainCam)
{
mCurrent = glm::mat4(1.0f);
mModelView = mModelView*mCurrent;
mProjection = *pipeline->getProjectionMatrix();
}
else
{
mModelView = projectorV;
mProjection = projectorP;
}
【问题讨论】:
标签: c++ opengl mapping textures glsl