全部, 我一直在遵循OpenGL纹理教程here,以便使用GLSL 1.2渲染纹理映射的地球球体。您可以下载源代码。但是我无法运行示例代码。它需要比我的工作簿支持的版本更高的OpenGL和GLSL(2016年末使用Iris GPU)。请注意,我使用的是斑点,过剩和土壤。但是我正在使用自己的数学库代替glm。
问题: 相同的纹理从右到左而不是从左到右映射。当然,这很容易说:只需在片段着色器中设置u = 1-u。但是,这不是根本问题。这是我感兴趣的理解。我将拥有比许多天体更多的物体上的多个摄像机。所有摄像机必须观测相同的世界。而且我担心,如果不了解相机的设置方式,将会比原作产生更多的返工。
第二遍时,我对视图和投影矩阵感到怀疑。我相信视图矩阵的生成方式与gluLookAt()相同(我认为它将视图矩阵设置为右手矩阵)。我相信投影矩阵也是在右手坐标中生成的。我一直偏向右偏,因为我读到OpenGL 2.1之前的某个版本之前,没有NDC的概念,并且OpenGL在MVP空间中偏右偏。
事不宜迟,这是我的LookAt:
void Matrix4d::LookAtRH(const Vector3d &eye, const Vector3d ¢er, const Vector3d &zenith) {
//functionally equivilent to gluLookAt()
//https://www.khronos.org/opengl/wiki/GluLookAt_code
Vector3d _look(center);
Vector3d forward(_look - eye);
forward.Normalize();
Vector3d right(forward);
right.Cross(zenith);
right.Normalize();
Vector3d up(right);
up.Cross(forward);
//rotate
m[0] = right.x; m[1] = up.x; m[2] = -forward.x; m[3] = 0;
m[4] = right.y; m[5] = up.y; m[6] = -forward.y; m[7] = 0;
m[8] = right.z; m[9] = up.z; m[10] = -forward.z; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
Translate(-eye.x, -eye.y, -eye.z);
}
void Matrix4d::Translate(double x, double y, double z) {
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
}
这是我的投影矩阵计算:
void Matrix4d::ProjectionViewRH(double fov_degrees, double aspectRatio, double near, double far) {
//https://www.gamedev.net/articles/programming/graphics/perspective-projections-in-lh-and-rh-systems-r3598/
double fov_radians = PI / 180.0 * fov_degrees;
double yScale = 1.0 / tan(fov_radians / 2.0);
double xScale = yScale / aspectRatio;
double nearToFar = far - near;
m[0] = (double)xScale;
m[1] = 0;
m[2] = 0;
m[3] = 0;
m[4] = 0;
m[5] = (double)yScale;
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = -(double)( (far + near) / nearToFar);
m[11] = -1;
m[12] = 0;
m[13] = 0;
m[14] = -(double)(2.0 * far*near / nearToFar);
m[15] = 0;
}
有人可以否认这些对于OpenGL 2.1环境是正确的吗?我完全想念什么吗?!
为了完整起见:
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitContextVersion(2, 1);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
glutInitWindowSize(WINDOW1_SIZE_X, WINDOW1_SIZE_Y); //optional
glutInitWindowPosition(50, 50);//optional
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
mainWindow = glutCreateWindow("Hello World");
glEnable(GL_DEPTH_TEST);
glutSetOption(GLUT_RENDERING_CONTEXT, GLUT_USE_CURRENT_CONTEXT);
subwindows[0] = glutCreateSubWindow(mainWindow, 0, 0, earthWindowDimensions[0], earthWindowDimensions[1]);
glutDisplayFunc(renderScene1);
glutIdleFunc(idleCallback1);
glutMouseWheelFunc(mouseWheelCallback1);
glutMouseFunc(mouseCallback1);
glutMotionFunc(motionCallback1);
motionCallback1(0, 0);
glutIdleFunc(idleCallback1);
…
}
这是渲染回调的流程:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glutSetWindow(mainWindow);
//glViewport(0, 0, mainWindowDimensions[0], mainWindowDimensions[1]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glutSwapBuffers();
glutSetWindow(subwindows[0]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene.DrawScene();
glutSwapBuffers();
垂直着色器:
void main(void) {
//pass these to fragment shader
NormalDir_World_f = (ModelMatrix * vec4(VertNormal_modelSpace, 0.0)).xyz; //0 in w component because normal is only a direction
ViewDir_World_f = -Eye_worldSpace;
LightPos_World_f = LightPosition_worldSpace;
AmbientColor_f = AmbientColor;
DiffuseColor_f = DiffuseColor;
SpecularColor_f = SpecularColor;
LightColor_f = LightColor;
texCoords_v2f = texCoords;
gl_Position = MVP * vec4(VertPosition_modelSpace, 1.0);
}
片段着色器:
void main(void) {
vec3 N = normalize(NormalDir_World_f);
vec3 E = normalize(ViewDir_World_f);
vec3 L = normalize(LightPos_World_f);
float cosTheta = dot(L,N);
vec3 diffuse = DiffuseColor_f * (LightColor_f * max(0.0, cosTheta));
vec3 R = reflect(-L, N);
vec3 V = normalize(-E);
float cosAlpha = dot(R, V);
vec3 specular = step(0.0, cosTheta) * (SpecularColor_f * (LightColor_f * pow(max(0.0, cosAlpha), 50.0) ));
//dont divide distance^2 here so light appears consistent regardless of model transforms
gl_FragColor = vec4(AmbientColor_f + diffuse + specular, 1.0) * texture2D(diffuseSampler, texCoords_v2f);
}
这些着色器是从一些运行良好的旧GLES素材中改编而成的。因此,不要在这里花费太多时间。