顶点着色器中的 Phong 光照

Posted

技术标签:

【中文标题】顶点着色器中的 Phong 光照【英文标题】:Phong Lighting in Vertex Shader 【发布时间】:2014-02-13 03:42:21 【问题描述】:

我正在尝试使用适用于 android 的 OpenGL ES 2.0 来显示具有法线和颜色的简单立方体。为此,我创建了一个着色器程序,附加我的顶点和片段着色器,并链接我的程序,如下所示:

// Create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
MyGLRenderer.checkGlError("glCreateProgram");

// Add the vertex shader to program
vertexShaderCode = Utilities.convertResourceToString(context, R.raw.vert_shader_hw3);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
GLES20.glAttachShader(mProgram, vertexShader);
MyGLRenderer.checkGlError("glAttachShader");

// Add the fragment shader to program
fragmentShaderCode = Utilities.convertResourceToString(context, R.raw.frag_shader_hw3);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
GLES20.glAttachShader(mProgram, fragmentShader);
MyGLRenderer.checkGlError("glAttachShader");

// Bind attributes
GLES20.glBindAttribLocation(mProgram, 0, "aPosition");
MyGLRenderer.checkGlError("glBindAttribLocation");

GLES20.glBindAttribLocation(mProgram, 1, "aNormal");
MyGLRenderer.checkGlError("glBindAttribLocation");

GLES20.glBindAttribLocation(mProgram, 2, "aColor");
MyGLRenderer.checkGlError("glBindAttribLocation");

// Create OpenGL program executables
GLES20.glLinkProgram(mProgram);
MyGLRenderer.checkGlError("glLinkProgram");

// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
MyGLRenderer.checkGlError("glUseProgram");

它在最后崩溃,打印到 LogCat:glUseProgram: glError 1281,我检查了文档,如果程序既不是 0 也不是 OpenGL 生成的值,则会生成 glError 1281,即GL_INVALID_VALUE

在谷歌上搜索了大约 10 个小时后,我决定向 *** 寻求帮助。知道我的顶点着色器代码有什么问题使 glUseProgram 以这种方式运行吗?

这是我的顶点着色器代码,我尝试实现 phong 光照:

uniform mat4 uMVPMatrix;
uniform mat4 uMVMatrix;
uniform vec3 uLightPosition;
uniform vec4 uAmbient;
uniform vec4 uDiffuse;
uniform vec4 uSpecular;
uniform vec4 uEmission;
uniform float uShininess;

attribute vec4 aPosition;
attribute vec3 aNormal;
attribute vec4 aColor;

varying vec4 vColor;

vec4 phong()

    //  P is the vertex coordinate on body
    vec3 P = vec3(uMVMatrix * aPosition);

    //  N is the object normal at P
    vec3 N = vec3(uMVMatrix * vec4(aNormal, 0.0)); 

    //  Light Position for light 0
    vec3 LightPos = uLightPosition;

    //  L is the light vector
    vec3 L = normalize(LightPos - P);

    //  R is the reflected light vector R = 2(L.N)N - L
    vec3 R = reflect(-L, N);

    //  V is the view vector (eye at the origin)
    vec3 V = normalize(-P);

    //  Diffuse light intensity is cosine of light and normal vectors
    float Id = max(dot(L,N) , 0.0);

    //  Shininess intensity is cosine of light and reflection vectors to a power
    float Is = (Id>0.0) ? pow(max(dot(R,V) , 0.0) , uShininess) : 0.0;

    //  Vertex color
    return uEmission + uAmbient + Id*uDiffuse + Is*uSpecular;


void main()

    gl_Position = uMVPMatrix * aPosition;
    vColor = phong() * 0.5*(gl_Position/gl_Position.w + 1.0);

【问题讨论】:

您是否使用 >> getIntegerv(MAX_VERTEX_ATTRIBS, &n) 之类的方法检查以确认硬件支持所需数量的属性 感谢您的快速回复。是的,我通过将其打印到 LogCat 来检查这一点。我的 Nexus 7 平板电脑上的 MAX_VERTEX_ATTRIBS 是 16。 您是否尝试检查 LINK_STATUS 和着色器信息日志? 【参考方案1】:

感谢各位的帮助。我终于弄明白了。问题是在我的顶点着色器中,我声明了“属性 vec4 aColor;”。然后在我的代码中,我尝试这样做:

mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, 16, colorsBuffer);

但是,aColor 从未在顶点着色器代码中实际使用过,而是在编译后的着色器中进行了优化,因此当我试图获取它的句柄并填充它时,它导致了我程序的其余部分失败。

【讨论】:

【参考方案2】:

我发现您在使用 checkGLError 时存在潜在问题。在MyGLRenderer.loadShader 之后没有检查错误。你能在那里添加一个检查,看看它是否真的编译正确(在glAttachShader之后的下一次错误检查之前)?请注意,loadShader 调用内部有 2 个 GL 调用 - 一个用于加载字符串,一个用于编译着色器本身。

vertexShaderCode = Utilities.convertResourceToString(context, R.raw.vert_shader_hw3);

int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);

GLES20.glAttachShader(mProgram, vertexShader); MyGLRenderer.checkGlError("glAttachShader");

【讨论】:

以上是关于顶点着色器中的 Phong 光照的主要内容,如果未能解决你的问题,请参考以下文章

WPF 中的逐像素光照

着色器中的 OpenGL 法线变换

验证顶点着色器中变换矩阵的使用。正确性或法线变换

在顶点着色器中将法线转换为视图空间

光照贴图

Phong 着色器不起作用