fix: OpenGL sphere test - correct perspective matrix, depth test, texture flip, and screenshot path

This commit is contained in:
2026-03-23 01:42:48 +08:00
parent f427699ac6
commit 537808c64d
2 changed files with 55 additions and 14 deletions

View File

@@ -24,6 +24,8 @@
#pragma comment(lib, "opengl32.lib")
#include <GL/gl.h>
using namespace XCEngine::RHI;
using namespace XCEngine::Debug;
using namespace XCEngine::Containers;
@@ -65,12 +67,12 @@ void TranslationMatrix(float* m, float x, float y, float z) {
void PerspectiveMatrix(float* m, float fov, float aspect, float nearZ, float farZ) {
memset(m, 0, 16 * sizeof(float));
float tanHalfFov = tanf(fov / 2.0f);
m[0] = 1.0f / (aspect * tanHalfFov);
m[5] = 1.0f / tanHalfFov;
m[10] = -(farZ + nearZ) / (farZ - nearZ);
m[11] = -1.0f;
m[14] = -(2.0f * farZ * nearZ) / (farZ - nearZ);
m[0] = 1.0f / (aspect * tanHalfFov); // m[0][0]
m[5] = 1.0f / tanHalfFov; // m[1][1]
m[10] = -(farZ + nearZ) / (farZ - nearZ); // m[2][2]
m[14] = -(2.0f * farZ * nearZ) / (farZ - nearZ); // m[2][3]
m[15] = 0.0f;
m[11] = -1.0f; // m[3][2] = -1 for OpenGL clip space
}
struct Vertex {
@@ -236,10 +238,16 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
float aspect = 1280.0f / 720.0f;
PerspectiveMatrix(projectionMatrix, 45.0f * 3.14159265f / 180.0f, aspect, 0.1f, 1000.0f);
shader.SetMat4("gModelMatrix", modelMatrix);
shader.SetMat4("gViewMatrix", viewMatrix);
shader.SetMat4("gProjectionMatrix", projectionMatrix);
shader.SetInt("uTexture", 0);
Log("[DEBUG] ProjectionMatrix:");
for (int i = 0; i < 4; i++) {
Log("[DEBUG] row%d: %.4f %.4f %.4f %.4f", i,
projectionMatrix[i*4], projectionMatrix[i*4+1], projectionMatrix[i*4+2], projectionMatrix[i*4+3]);
}
Log("[DEBUG] ModelMatrix:");
for (int i = 0; i < 4; i++) {
Log("[DEBUG] row%d: %.4f %.4f %.4f %.4f", i,
modelMatrix[i*4], modelMatrix[i*4+1], modelMatrix[i*4+2], modelMatrix[i*4+3]);
}
OpenGLPipelineState pipelineState;
OpenGLRasterizerState rasterizerState;
@@ -247,8 +255,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
pipelineState.SetRasterizerState(rasterizerState);
OpenGLDepthStencilState depthStencilState;
depthStencilState.depthTestEnable = false;
depthStencilState.depthWriteEnable = false;
depthStencilState.depthTestEnable = true;
depthStencilState.depthWriteEnable = true;
depthStencilState.depthFunc = ComparisonFunc::Less;
pipelineState.SetDepthStencilState(depthStencilState);
ViewportState viewportState = { 0.0f, 0.0f, (float)gWidth, (float)gHeight, 0.0f, 1.0f };
@@ -257,6 +266,16 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
pipelineState.AttachShader(shader.GetID());
pipelineState.Apply();
Log("[DEBUG] Shader program ID: %u", shader.GetID());
int modelLoc = shader.GetUniformLocation("gModelMatrix");
int viewLoc = shader.GetUniformLocation("gViewMatrix");
int projLoc = shader.GetUniformLocation("gProjectionMatrix");
Log("[DEBUG] Uniform locations - gModelMatrix: %d, gViewMatrix: %d, gProjectionMatrix: %d", modelLoc, viewLoc, projLoc);
shader.SetMat4("gModelMatrix", modelMatrix);
shader.SetMat4("gViewMatrix", viewMatrix);
shader.SetMat4("gProjectionMatrix", projectionMatrix);
shader.SetInt("uTexture", 0);
OpenGLTexture texture;
if (!texture.LoadFromFile("Res/Image/earth.png", true)) {
Log("[ERROR] Failed to load texture");
@@ -276,6 +295,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
int frameCount = 0;
const int targetFrameCount = 30;
int renderCount = 0;
while (frameCount < targetFrameCount) {
if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
@@ -284,17 +304,30 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
renderCount++;
GLenum err = glGetError();
if (err != GL_NO_ERROR) Log("[DEBUG] GL error before clear: 0x%x", err);
commandList.SetViewport(0, 0, gWidth, gHeight);
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1);
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1 | 2); // COLOR_BUFFER | DEPTH_BUFFER
err = glGetError();
if (err != GL_NO_ERROR) Log("[DEBUG] GL error after clear: 0x%x", err);
pipelineState.Bind();
err = glGetError();
if (err != GL_NO_ERROR) Log("[DEBUG] GL error after pipeline bind: 0x%x", err);
indexBuffer.Bind();
vertexArray.Bind();
texture.Bind(0);
sampler.Bind(0);
err = glGetError();
if (err != GL_NO_ERROR) Log("[DEBUG] GL error before draw: 0x%x", err);
commandList.DrawIndexed(PrimitiveType::Triangles, (uint32_t)indices.size(), 0, 0);
swapChain.Present(0, 0);
@@ -302,8 +335,15 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
}
}
Log("[INFO] Rendered %d frames (target was %d)", renderCount, targetFrameCount);
Log("[INFO] Reached target frame count %d - taking screenshot!", targetFrameCount);
OpenGLScreenshot::Capture(device, swapChain, "sphere.ppm");
char exePath[MAX_PATH];
GetModuleFileNameA(NULL, exePath, MAX_PATH);
char* lastSlash = strrchr(exePath, '\\');
if (lastSlash) *lastSlash = '\0';
strcat_s(exePath, "\\sphere.ppm");
OpenGLScreenshot::Capture(device, swapChain, exePath);
sampler.Shutdown();
texture.Shutdown();