GLSL中的纹理投影

问题描述 投票:4回答:1

我正在尝试直接基于此示例的oZone3d来实现纹理投影。我的环境是Android 2.2上的OpenGL ES 2.0。

矩阵数学从来都不是我的强项,我怀疑我的问题出在纹理投影矩阵设置(texGenMatrix)中。我已经尽一切努力使此工作可行,但投影效果不正确。我非常感谢您对我的代码有更多的关注。谢谢。

这里未显示我的几何图形(通过原点的水平面),以及其他一些管道,例如着色器统一/属性绑定。

相机设置:

// Set the camera projection matrix 
Matrix.frustumM(cameraProjMatrix, 0, 
    -nearPlaneSize.x, nearPlaneSize.x,  // near plane left/right
    -nearPlaneSize.y, nearPlaneSize.y,  // near plane bottom/top
    nearPlaneDistance, farPlaneDistance // near/far plane distance
);

// Set the camera view matrix
Matrix.setLookAtM(cameraViewMatrix, 0, 
    0, 100, 100,  // eye
    0, 0, 0,  // center
    0, 1, 0 // up-vector
);

// Translate the model as needed
Matrix.translateM(modelMatrix, 0, x, y, z);

// Calculate the model * view matrix
Matrix.multiplyMM(modelViewMatrix, 0, cameraViewMatrix, 0, modelMatrix, 0);

// Calculate the inverse camera view matrix (needed in the vert shader)
Matrix.invertM(inverseCameraViewMatrix, 0, cameraViewMatrix, 0);

纹理投影设置:

// Set a texture projection matrix
Matrix.frustumM(texProjMatrix, 0, 
    -nearPlaneSize.x, nearPlaneSize.x,  // near plane left/right
    -nearPlaneSize.y, nearPlaneSize.y,  // near plane bottom/top
    nearPlaneDistance, farPlaneDistance // near/far plane distance
);


// Set the texture projection to point down at the origin
Matrix.setLookAtM(texViewMatrix, 0, 
    0, 100, 10,  // eye
    0, 0, 0,  // center
    0, 1, 0 // up-vector
);

 // scale bias
float[] scaleBiasMatrix = new float[] { 0.5f, 0.0f, 0.0f, 0.0f,
                                       0.0f, 0.5f, 0.0f, 0.0f,
                                       0.0f, 0.0f, 0.5f, 0.0f,
                                       0.5f, 0.5f, 0.5f, 1.0f
};

// calculate the TexGenMatrix 
Matrix.multiplyMM(texGenMatrix, 0, scaleBiasMatrix, 0, texProjMatrix, 0);
Matrix.multiplyMM(texGenMatrix, 0, texGenMatrix, 0, texViewMatrix, 0);

顶点着色器:

attribute vec3 aPosition; // vertex x y z 

uniform mat4 texGenMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 cameraProjMatrix;

varying vec4 vProjCoord;

void main() {
    gl_Position = cameraProjMatrix * modelViewMatrix * aPosition;
    vec4 posEye = modelViewMatrix * aPosition;
    vec4 posWorld = inverseCameraViewMatrix * posEye;
    vProjCoord = texGenMatrix * posWorld;
}

片段着色器:

uniform sampler2D projectionMap;     
varying vec4 vProjCoord;

void main() {
    vec3 finalColor = vec3( 0.5, 0.5, 0.5);
    if (vProjCoord.q > 0.0) {
        vec4 ProjMapColor = texture2DProj(projectionMap, vProjCoord);
        finalColor += ProjMapColor.rgb;
    }
    gl_FragColor = vec4(finalColor, 1.0);
}
glsl textures projection
1个回答
0
投票

我认为,如果您指定在屏幕上看到的内容以及收到的错误消息,这会有所帮助。

我进行了投影映射,并将其与代码进行了比较,我怀疑顶点着色器代码。

您代码中的aPosition似乎是世界框架上的顶点坐标。 gl_Position是在屏幕上应用模型视图/投影矩阵的位置,因此您的计算是正确的,但是vProjCoord必须通过直接将纹理生成矩阵与世界坐标相乘来计算。对于矩阵乘法,使用vec4比vec3 aPosition更好。这是我的工作代码:

// Vertex shader
const char* vsSource = R"(
// GLSL version
#version 130
// uniforms
uniform mat4 TexgenMat1;
uniform mat4 TexgenMat2;
uniform mat4 TexgenMat3;
uniform mat4 TexgenMat4;
// vertex attribs (input)
attribute vec3 vertexPosition;
attribute vec3 vertexNormal;
attribute vec2 vertexTexCoord;
// varying
// varying variable is interpolated between vertices before processing fragment shader.
varying vec4 texcoord[4];
void main()
{
    vec4 posEye = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(vertexPosition, 1.0);
    texcoord[0] = TexgenMat1 * vec4(vertexPosition, 1.0);
    texcoord[1] = TexgenMat2 * vec4(vertexPosition, 1.0);
    texcoord[2] = TexgenMat3 * vec4(vertexPosition, 1.0);
    texcoord[3] = TexgenMat4 * vec4(vertexPosition, 1.0);
    gl_Position = posEye;
}
)";

如果仅在要投影的范围内投影图像,则必须考虑投影坐标w.r.t的第一个,第二个元素。它的最后一个元素(例如vProjCoord.s/vProjCoord.q)。

这是我的工作代码:

// Fragment shader
const char* fsSource = R"(
// GLSL version
#version 130
// uniforms
uniform sampler2D proj_tex;
uniform float projection_alpha;
// varying
varying vec4 texcoord[4];
void main()
{
    vec4 base_color = vec4(0.3, 0.3, 0.3, 1.0);
    vec4 frag_color = vec4(0.0, 0.0, 0.0, 1.0);
    int overlap = 0;
    // gl_TexCoord[i] = vec4(s, t, p, q); , homogeneous
    for (int i=0;i<4;i++){
        if (texcoord[i].q > 0.0){
                        if ((texcoord[i].s/texcoord[i].q<0.0) || 
(texcoord[i].s/texcoord[i].q>1.0)||
                            (texcoord[i].t/texcoord[i].q<0.0) || 
(texcoord[i].t/texcoord[i].q>1.0))
                        { 
                            //frag_color += base_color * texture_alpha;
                        }
                        else
                        {
                            vec4 ProjColor = texture2DProj(proj_tex, texcoord[i]);
                            frag_color += ProjColor;
                            overlap++;
                        }
        }
    }
    if (overlap == 0){
        frag_color=base_color;
    }
    else{
        frag_color /= overlap;
        frag_color = frag_color*projection_alpha + base_color * ( 1 - projection_alpha );
    }
    // set frag color
    gl_FragColor = frag_color;
}
)";

这是我的结果:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.