Ich versuche, eine einfache projektive Textur-Mapping-Ansatz mit Shadern in OpenGL 3+ zu implementieren. Obwohl es einige Beispiele im Web gibt, habe ich Probleme, ein funktionierendes Beispiel mit Shadern zu erstellen.OpenGL projektive Textur-Mapping über Shader
Ich plane eigentlich die Verwendung von zwei Shadern, eine, die eine normale Szene zeichnet, und eine andere für projektive Textur-Mapping. Ich habe eine Funktion zum Zeichnen einer Szene void ProjTextureMappingScene::renderScene(GLFWwindow *window)
und ich benutze glUseProgram(), um zwischen Shadern zu wechseln. Die normale Zeichnung funktioniert gut. Es ist mir jedoch unklar, wie ich die projektive Textur auf einen bereits texturierten Würfel auftragen soll. Muss ich irgendwie einen Stencil-Puffer oder ein Framebuffer-Objekt verwenden (der Rest der Szene sollte davon nicht betroffen sein)?
Ich glaube auch nicht, dass meine projektiven Textur Mapping Shader richtig sind, seit dem zweiten Mal, wenn ich einen Würfel render es schwarz zeigt. Außerdem habe ich versucht, mit Farben zu debuggen, und nur die t
Komponente des Shaders scheint nicht Null zu sein (der Würfel erscheint also grün). Ich überschreibe die texColor
im Fragment-Shader unten nur für Debugging-Zwecke.
Vertexshader
#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);
}
FragmentShader
#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);
}
}
Erstellung von TexGen Matrix
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);
Render Cube wieder
Es ist mir auch unklar, was die Modellansicht des Würfels sein sollte? Sollte es die Ansichtsmatrix vom Diaprojektor (wie es jetzt ist) oder vom normalen Ansichtsprojektor verwenden? Gegenwärtig wird der Würfel in der Mitte der Szenenansicht schwarz (oder grün, wenn debuggen) gerendert, wie es vom Diaprojektor erscheinen würde (Ich habe einen Umschalt-Hotkey gemacht, damit ich sehen kann, was der Diaprojektor "sieht"). Der Würfel bewegt sich auch mit der Ansicht. Wie bekomme ich die Projektion auf den Würfel selbst?
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);
Umschalten zwischen Hauptszene Kamera und Diaprojektor Kamera
if (useMainCam)
{
mCurrent = glm::mat4(1.0f);
mModelView = mModelView*mCurrent;
mProjection = *pipeline->getProjectionMatrix();
}
else
{
mModelView = projectorV;
mProjection = projectorP;
}