OpenGL着色器光照位置在着色器中改变
OpenGL shader light position changed in shader
首先,如果标题误导了我,我很抱歉,但我不太确定如何描述这个问题,如果这是一个问题的话。
我是一个全新的OpenGL,我刚刚开始刮伤表面的GLSL跟随本教程。
渲染函数的主要部分如下所示
GLfloat ambientLight[] = {0.5f, 0.5f, 0.5f, 1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
//Add directed light
GLfloat lightColor1[] = {0.5f, 0.5f, 0.5f, 1.0f}; //Color (0.5, 0.2, 0.2)
//Coming from the direction (-1, 0.5, 0.5)
GLfloat lightPos1[] = { 40.0 * cos((float) elapsed_time / 500.0) , 40.0 * sin((float) elapsed_time / 500.0), -20.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor1);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos1);
glPushMatrix();
glTranslatef(0,0,-50);
glColor3f(1.0, 1.0, 1.0);
glRotatef( (float) elapsed_time / 100.0, 0.0,1.0,0.0 );
glUseProgram( shaderProg );
glutSolidTeapot( 10 );
glPopMatrix();
其中"shaderProg"是一个由顶点着色器组成的着色程序
varying vec3 normal;
void main(void)
{
normal = gl_Normal;
gl_Position = ftransform();
}
和一个片段着色器
uniform vec3 lightDir;
varying vec3 normal;
void main() {
float intensity;
vec4 color;
intensity = dot(vec3(gl_LightSource[0].position), normalize(normal));
if (intensity > 0.95)
color = vec4(1.0,0.5,0.5,1.0);
else if (intensity > 0.5)
color = vec4(0.6,0.3,0.3,1.0);
else if (intensity > 0.25)
color = vec4(0.4,0.2,0.2,1.0);
else
color = vec4(0.2,0.1,0.1,1.0);
gl_FragColor = color;
}
我有两个问题
首先,根据教程,统一的lightDir应该是可用的,但我只得到vec3(gl_LightSource[0].position)的结果。这两者有什么区别吗?
另一个问题是,当使用着色器程序时,设置围绕茶壶旋转的光线不同。没有着色器,光线在相机的XY轴上围绕茶壶旋转。然而,如果使用了着色器,光线会沿着相机的XZ轴移动。我错了吗?还是我忘记了一些着色器的翻译?
提前感谢:)
首先,根据教程,统一的lightDir应该是可用,但我只得到vec3(gl_LightSource[0].position)的结果。这两者有什么区别吗?
该教程使用lightDir
作为统一变量。你必须自己设定。通过glUniform
呼叫。是否相同取决于你在这里设置的光源位置。这里使用的lightDir
是从表面点到光源的矢量,你想要遮阳。本教程使用方向光,所以光线方向在场景中的任何地方都是相同的,并不真正依赖于顶点/片段的位置。通过将光源位置的w
分量设置为0,可以对固定功能照明进行相同的操作。如果你不这样做,结果将会非常不同。
旁注:不幸的是,该教程中的GLSL代码依赖于许多已弃用的特性。如果你学习GLSL,我强烈建议你学习现代GL核心配置文件。
lightDir
不是预定义的统一。光方向矢量的典型定义是你的着色器中光位置的标准化矢量,你可以通过规范化位置矢量轻松计算:
vec3 lightDir = normalize(gl_LightSource[0].position.xyz);
你也可以把它作为你自己定义的统一传递到着色器中。对于这种方法,你将在你的片段着色器中定义统一:
uniform vec3 lightDir;
,然后通过glGetUniformLocation()
调用获得统一的位置,并通过glUniform3f()
调用设置一个值。链接完着色器后,你会看到:
GLint lightDirLoc = glGetUniformLocation(shaderProg, "lightDir");
,然后每次你想改变光的方向为(vx, vy, vz)
:
glUniform3f(lightDirLoc, vx, vy, vz);
对于你的问题的第二部分:与你自己的着色器相比,你用固定管道得到的光位置的不同行为的原因是固定管道将当前的模型视图矩阵应用到指定的光位置,这在你的着色器中没有完成。
正如许多其他人已经建议的那样:如果你现在学习OpenGL,我强烈建议你跳过遗留特性,其中包括固定函数光源参数。在这种情况下,您可以简单地使用自己定义的uniform
变量,正如我已经说明的那样,作为上面lightDir
变量的选项。
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 变量没有改变?通过向量的函数调用
- 了解 GLM- openGL 中的相机转换
- 如何在全屏模式下(在OpenGL中)使背景透明
- 为什么我不能使用 EGL 创建无头 OpenGl 上下文?
- 旋转三角形并在opengl中改变其颜色
- 全局变量的顺序会改变C /OpenGL的性能
- OpenGL改变生成的纹理的颜色
- OpenGL不会改变纹理
- 如何在opengl中改变放入顶点缓冲区的值
- 如何使用OpenGL和GLSL来改变颜色(c++)
- glColor实际上并没有改变OpenGL的颜色
- OpenGL着色器光照位置在着色器中改变
- SDL2 OpenGL窗口缩小和改变鼠标坐标
- OpenGL在可分离着色器程序中改变不同的位置
- 如何在opengl中改变纹理的HSV
- 在openGL中改变三角形坐标
- Android:如何动态改变OpenGL ES纹理图像
- 如何在openGL, c++中改变视角
- 试着做一个世界网格,我可以随意改变c++ OpenGL