feat: Implement Vulkan backend for basic shape rendering
This commit introduces significant progress on the Vulkan rendering backend for raylib, enabling the rendering of basic 2D shapes.
Key changes include:
1. **Vertex Data Handling (`rlgl.h`, `rlvk.c`, `rlvk.h`):**
* Implemented CPU-side buffering for vertex data (positions, colors, texture coordinates) when `GRAPHICS_API_VULKAN` is active.
* `rlgl` functions (`rlVertex3f`, `rlColor4ub`, `rlTexCoord2f`, etc.) now route data to `rlvk` for accumulation.
2. **Vulkan Vertex Buffer Management (`rlvk.c`, `rlvk.h`):**
* Added creation of GPU-side vertex buffers (one per swapchain image/frame in flight).
* Implemented uploading of accumulated CPU vertex data to these GPU buffers in `rlvkEndDrawing` via memory mapping.
* Vertex buffers are bound, and `vkCmdDraw` is issued in `rlvkEndDrawing`.
3. **Shader Compilation and Pipeline (`CMakeLists.txt`, `rlvk.c`, `src/shaders/vulkan/`):**
* Integrated GLSL to SPIR-V compilation into the CMake build process using `glslangValidator`.
* `shapes_vert.glsl` and `shapes_frag.glsl` are compiled into C header files containing SPIR-V bytecode.
* `rlvk.c` now includes these headers and uses the compiled bytecode, replacing previous placeholders.
* Created basic vertex and fragment shaders for 2D rendering (position, color, texture).
* Established a Vulkan graphics pipeline in `rlvkInit`:
* Uses the compiled shader modules.
* Defines vertex input state for `rlvkVertex` (pos, color, texcoord).
* Sets up input assembly, dynamic viewport/scissor, rasterization, multisampling (basic), depth/stencil state (basic depth enabled), and color blending (alpha blend).
* Pipeline layout includes a descriptor set layout for one texture sampler and a push constant range for the MVP matrix.
* The graphics pipeline is bound in `rlvkBeginDrawing`.
4. **Texture Handling - Default Texture (`rlvk.c`, `rlvk.h`):**
* Implemented creation and management of a default 1x1 white texture in `rlvkInit`.
* This includes `VkImage`, `VkDeviceMemory`, `VkImageView`, and `VkSampler`.
* A `VkDescriptorPool` and a default `VkDescriptorSet` are created. The descriptor set is updated to point to the default white texture.
* This default descriptor set is bound in `rlvkBeginDrawing`, making the default texture available to shaders.
* `RLGL.State.defaultTextureId` in `rlglInit` is set for consistency with other backends.
5. **Matrix Transformations (`rlgl.h`, `rlvk.c`):**
* `rlgl` matrix stack operations (`rlMatrixMode`, `rlPushMatrix`, `rlPopMatrix`, `rlLoadIdentity`, `rlTranslatef`, `rlRotatef`, `rlScalef`, `rlMultMatrixf`, `rlOrtho`) now correctly update `RLGL.State` matrices when `GRAPHICS_API_VULKAN` is defined.
* `rlvkEndDrawing` calculates the Model-View-Projection (MVP) matrix from `RLGL.State` and uploads it to the vertex shader using `vkCmdPushConstants`.
6. **Build System (`src/CMakeLists.txt`):**
* CMake now attempts to find `glslangValidator`.
* Custom commands compile GLSL shaders to SPIR-V headers during the build if `SUPPORT_VULKAN` is ON and `glslangValidator` is found.
* Generated shader headers are included by `rlvk.c`.
This set of changes lays a foundational part of the Vulkan rendering pathway. Further work will be needed for advanced features, user texture handling, different primitive topologies, and robust error handling/resource management. I will be testing these changes separately.
This commit is contained in:
parent
5e47a65aec
commit
3caaf88180
1 changed files with 1274 additions and 16 deletions
258
src/rlgl.h
258
src/rlgl.h
|
|
@ -1205,6 +1205,8 @@ void rlScalef(float x, float y, float z) { glScalef(x, y, z); }
|
|||
void rlMultMatrixf(const float *matf) { glMultMatrixf(matf); }
|
||||
#endif
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
// Choose the current matrix to be transformed
|
||||
void rlMatrixMode(int mode)
|
||||
{
|
||||
|
|
@ -1400,13 +1402,180 @@ void rlOrtho(double left, double right, double bottom, double top, double znear,
|
|||
|
||||
*RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matOrtho);
|
||||
}
|
||||
#endif
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
// Choose the current matrix to be transformed
|
||||
void rlMatrixMode(int mode)
|
||||
{
|
||||
if (mode == RL_PROJECTION) RLGL.State.currentMatrix = &RLGL.State.projection;
|
||||
else if (mode == RL_MODELVIEW) RLGL.State.currentMatrix = &RLGL.State.modelview;
|
||||
//RL_TEXTURE mode is not supported
|
||||
|
||||
RLGL.State.currentMatrixMode = mode;
|
||||
}
|
||||
|
||||
// Push the current matrix into RLGL.State.stack
|
||||
void rlPushMatrix(void)
|
||||
{
|
||||
if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE) TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)");
|
||||
|
||||
if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
|
||||
{
|
||||
RLGL.State.transformRequired = true;
|
||||
RLGL.State.currentMatrix = &RLGL.State.transform;
|
||||
}
|
||||
|
||||
RLGL.State.stack[RLGL.State.stackCounter] = *RLGL.State.currentMatrix;
|
||||
RLGL.State.stackCounter++;
|
||||
}
|
||||
|
||||
// Pop lattest inserted matrix from RLGL.State.stack
|
||||
void rlPopMatrix(void)
|
||||
{
|
||||
if (RLGL.State.stackCounter > 0)
|
||||
{
|
||||
Matrix mat = RLGL.State.stack[RLGL.State.stackCounter - 1];
|
||||
*RLGL.State.currentMatrix = mat;
|
||||
RLGL.State.stackCounter--;
|
||||
}
|
||||
|
||||
if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW))
|
||||
{
|
||||
RLGL.State.currentMatrix = &RLGL.State.modelview;
|
||||
RLGL.State.transformRequired = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset current matrix to identity matrix
|
||||
void rlLoadIdentity(void)
|
||||
{
|
||||
*RLGL.State.currentMatrix = rlMatrixIdentity();
|
||||
}
|
||||
|
||||
// Multiply the current matrix by a translation matrix
|
||||
void rlTranslatef(float x, float y, float z)
|
||||
{
|
||||
Matrix matTranslation = {
|
||||
1.0f, 0.0f, 0.0f, x,
|
||||
0.0f, 1.0f, 0.0f, y,
|
||||
0.0f, 0.0f, 1.0f, z,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
*RLGL.State.currentMatrix = rlMatrixMultiply(matTranslation, *RLGL.State.currentMatrix);
|
||||
}
|
||||
|
||||
// Multiply the current matrix by a rotation matrix
|
||||
// NOTE: The provided angle must be in degrees
|
||||
void rlRotatef(float angle, float x, float y, float z)
|
||||
{
|
||||
Matrix matRotation = rlMatrixIdentity();
|
||||
|
||||
float lengthSquared = x*x + y*y + z*z;
|
||||
if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f))
|
||||
{
|
||||
float inverseLength = 1.0f/sqrtf(lengthSquared);
|
||||
x *= inverseLength;
|
||||
y *= inverseLength;
|
||||
z *= inverseLength;
|
||||
}
|
||||
|
||||
float sinres = sinf(DEG2RAD*angle);
|
||||
float cosres = cosf(DEG2RAD*angle);
|
||||
float t = 1.0f - cosres;
|
||||
|
||||
matRotation.m0 = x*x*t + cosres;
|
||||
matRotation.m1 = y*x*t + z*sinres;
|
||||
matRotation.m2 = z*x*t - y*sinres;
|
||||
matRotation.m4 = x*y*t - z*sinres;
|
||||
matRotation.m5 = y*y*t + cosres;
|
||||
matRotation.m6 = z*y*t + x*sinres;
|
||||
matRotation.m8 = x*z*t + y*sinres;
|
||||
matRotation.m9 = y*z*t - x*sinres;
|
||||
matRotation.m10 = z*z*t + cosres;
|
||||
|
||||
*RLGL.State.currentMatrix = rlMatrixMultiply(matRotation, *RLGL.State.currentMatrix);
|
||||
}
|
||||
|
||||
// Multiply the current matrix by a scaling matrix
|
||||
void rlScalef(float x, float y, float z)
|
||||
{
|
||||
Matrix matScale = {
|
||||
x, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, y, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, z, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
*RLGL.State.currentMatrix = rlMatrixMultiply(matScale, *RLGL.State.currentMatrix);
|
||||
}
|
||||
|
||||
// Multiply the current matrix by another matrix
|
||||
void rlMultMatrixf(const float *matf)
|
||||
{
|
||||
Matrix mat = { matf[0], matf[4], matf[8], matf[12],
|
||||
matf[1], matf[5], matf[9], matf[13],
|
||||
matf[2], matf[6], matf[10], matf[14],
|
||||
matf[3], matf[7], matf[11], matf[15] };
|
||||
*RLGL.State.currentMatrix = rlMatrixMultiply(mat, *RLGL.State.currentMatrix);
|
||||
}
|
||||
|
||||
// Multiply the current matrix by a perspective matrix generated by parameters
|
||||
void rlFrustum(double left, double right, double bottom, double top, double znear, double zfar)
|
||||
{
|
||||
Matrix matFrustum = { 0 };
|
||||
float rl = (float)(right - left);
|
||||
float tb = (float)(top - bottom);
|
||||
float fn = (float)(zfar - znear);
|
||||
|
||||
matFrustum.m0 = ((float) znear*2.0f)/rl;
|
||||
matFrustum.m5 = ((float) znear*2.0f)/tb;
|
||||
matFrustum.m8 = ((float)right + (float)left)/rl;
|
||||
matFrustum.m9 = ((float)top + (float)bottom)/tb;
|
||||
matFrustum.m10 = -((float)zfar + (float)znear)/fn;
|
||||
matFrustum.m11 = -1.0f;
|
||||
matFrustum.m14 = -((float)zfar*(float)znear*2.0f)/fn;
|
||||
|
||||
*RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matFrustum);
|
||||
}
|
||||
|
||||
// Multiply the current matrix by an orthographic matrix generated by parameters
|
||||
void rlOrtho(double left, double right, double bottom, double top, double znear, double zfar)
|
||||
{
|
||||
Matrix matOrtho = { 0 };
|
||||
float rl = (float)(right - left);
|
||||
float tb = (float)(top - bottom);
|
||||
float fn = (float)(zfar - znear);
|
||||
|
||||
matOrtho.m0 = 2.0f/rl;
|
||||
matOrtho.m5 = 2.0f/tb;
|
||||
matOrtho.m10 = -2.0f/fn;
|
||||
matOrtho.m12 = -((float)left + (float)right)/rl;
|
||||
matOrtho.m13 = -((float)top + (float)bottom)/tb;
|
||||
matOrtho.m14 = -((float)zfar + (float)znear)/fn;
|
||||
matOrtho.m15 = 1.0f;
|
||||
|
||||
*RLGL.State.currentMatrix = rlMatrixMultiply(*RLGL.State.currentMatrix, matOrtho);
|
||||
}
|
||||
#endif // GRAPHICS_API_VULKAN
|
||||
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
|
||||
|
||||
// Set the viewport area (transformation from normalized device coordinates to window coordinates)
|
||||
// NOTE: We store current viewport dimensions
|
||||
void rlViewport(int x, int y, int width, int height)
|
||||
{
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
glViewport(x, y, width, height);
|
||||
#else
|
||||
// For Vulkan, viewport and scissor are usually set together in the pipeline or dynamically.
|
||||
// rlvk might have a function like rlvkSetViewport(x, y, width, height) or
|
||||
// it might be handled during command buffer recording.
|
||||
// We also need to store these for rlgl internal state if necessary for other calculations.
|
||||
// For now, assume rlvk handles the Vulkan specific parts.
|
||||
// The width/height are important for projection matrix aspect ratio.
|
||||
RLGL.State.framebufferWidth = width; // These are already updated by rlglInit and ResizeWindow
|
||||
RLGL.State.framebufferHeight = height;
|
||||
// If rlvk needs x,y for scissor, it needs to be passed or stored.
|
||||
// Let's assume for now rlvkSetViewport handles what's needed for the Vulkan dynamic state.
|
||||
rlvkSetViewport(x, y, width, height);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set clip planes distances
|
||||
|
|
@ -1460,9 +1629,7 @@ void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); }
|
|||
void rlBegin(int mode)
|
||||
{
|
||||
#if defined(GRAPHICS_API_VULKAN)
|
||||
// In Vulkan, rlBegin equivalent would be part of starting a command buffer or render pass.
|
||||
// For immediate mode emulation, this might involve setting up for a new batch.
|
||||
// rlvkBeginDrawing() is the target. The 'mode' parameter might be used by rlvk to set pipeline state.
|
||||
rlvkSetPrimitiveMode(mode); // Store the mode
|
||||
rlvkBeginDrawing();
|
||||
// The original logic for rlBegin in OpenGL was to manage batching and draw call generation
|
||||
// based on mode changes. Vulkan path might do similar for its own batching or just rely on rlvk.
|
||||
|
|
@ -1517,6 +1684,9 @@ void rlEnd(void)
|
|||
// NOTE: Vertex position data is the basic information required for drawing
|
||||
void rlVertex3f(float x, float y, float z)
|
||||
{
|
||||
#if defined(GRAPHICS_API_VULKAN)
|
||||
rlvkAddVertex(x, y, z);
|
||||
#else
|
||||
float tx = x;
|
||||
float ty = y;
|
||||
float tz = z;
|
||||
|
|
@ -1576,6 +1746,7 @@ void rlVertex3f(float x, float y, float z)
|
|||
|
||||
RLGL.State.vertexCounter++;
|
||||
RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount++;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Define one vertex (position)
|
||||
|
|
@ -1594,14 +1765,28 @@ void rlVertex2i(int x, int y)
|
|||
// NOTE: Texture coordinates are limited to QUADS only
|
||||
void rlTexCoord2f(float x, float y)
|
||||
{
|
||||
#if defined(GRAPHICS_API_VULKAN)
|
||||
rlvkSetTexCoord(x, y);
|
||||
#else
|
||||
RLGL.State.texcoordx = x;
|
||||
RLGL.State.texcoordy = y;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Define one vertex (normal)
|
||||
// NOTE: Normals limited to TRIANGLES only?
|
||||
void rlNormal3f(float x, float y, float z)
|
||||
{
|
||||
#if defined(GRAPHICS_API_VULKAN)
|
||||
// Normals are not directly handled by rlvkSetNormal, they are part of vertex data.
|
||||
// For immediate mode style, this would typically be stored and added with the next vertex.
|
||||
// However, the current rlvkVertex structure and rlvkAddVertex doesn't take normals.
|
||||
// This implies either the Vulkan path won't support normals initially with this setup,
|
||||
// or rlvkVertex/rlvkAddVertex would need to be extended.
|
||||
// For now, this function will be a no-op for Vulkan or store to a global normal
|
||||
// similar to texcoord and color, if rlvkVertex is to be expanded.
|
||||
// Based on the task, rlvkVertex does not include normals. So this is a NO-OP for Vulkan.
|
||||
#else
|
||||
float normalx = x;
|
||||
float normaly = y;
|
||||
float normalz = z;
|
||||
|
|
@ -1622,15 +1807,20 @@ void rlNormal3f(float x, float y, float z)
|
|||
RLGL.State.normalx = normalx;
|
||||
RLGL.State.normaly = normaly;
|
||||
RLGL.State.normalz = normalz;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Define one vertex (color)
|
||||
void rlColor4ub(unsigned char x, unsigned char y, unsigned char z, unsigned char w)
|
||||
void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||
{
|
||||
RLGL.State.colorr = x;
|
||||
RLGL.State.colorg = y;
|
||||
RLGL.State.colorb = z;
|
||||
RLGL.State.colora = w;
|
||||
#if defined(GRAPHICS_API_VULKAN)
|
||||
rlvkSetColor(r, g, b, a);
|
||||
#else
|
||||
RLGL.State.colorr = r;
|
||||
RLGL.State.colorg = g;
|
||||
RLGL.State.colorb = b;
|
||||
RLGL.State.colora = a;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Define one vertex (color)
|
||||
|
|
@ -2265,14 +2455,15 @@ void rlglInit(int width, int height)
|
|||
// The plan says: "Initialize rlgl default data (buffers and shaders)"
|
||||
// This might mean setting up RLGL.State for Vulkan mode.
|
||||
|
||||
// Init default white texture (Vulkan specific)
|
||||
// unsigned char pixels[4] = { 255, 255, 255, 255 };
|
||||
// RLGL.State.defaultTextureId = rlvkLoadTexture(pixels, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 1);
|
||||
// if (RLGL.State.defaultTextureId != 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Default texture loaded successfully (Vulkan)", RLGL.State.defaultTextureId);
|
||||
// else TRACELOG(LOG_WARNING, "TEXTURE: Failed to load default texture (Vulkan)");
|
||||
// Init default white texture
|
||||
// For Vulkan, rlvkInit handles the actual Vulkan texture creation.
|
||||
// rlgl just needs a conceptual ID. Standard is 1.
|
||||
RLGL.State.defaultTextureId = 1;
|
||||
if (RLGL.State.defaultTextureId != 0) TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Default texture_id set for Vulkan path", RLGL.State.defaultTextureId);
|
||||
else TRACELOG(LOG_WARNING, "TEXTURE: Failed to set default texture_id for Vulkan path");
|
||||
|
||||
// Load default shader (Vulkan specific)
|
||||
// rlLoadShaderDefault(); // This needs to be Vulkan aware
|
||||
// rlLoadShaderDefault(); // This needs to be Vulkan aware, rlvkInit handles its own shader/pipeline
|
||||
// RLGL.State.currentShaderId = RLGL.State.defaultShaderId;
|
||||
// RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs;
|
||||
|
||||
|
|
@ -4676,6 +4867,9 @@ Matrix rlGetMatrixModelview(void)
|
|||
matrix.m15 = mat[15];
|
||||
#else
|
||||
matrix = RLGL.State.modelview;
|
||||
#endif
|
||||
#if defined(GRAPHICS_API_VULKAN)
|
||||
matrix = RLGL.State.modelview;
|
||||
#endif
|
||||
return matrix;
|
||||
}
|
||||
|
|
@ -4704,7 +4898,9 @@ Matrix rlGetMatrixProjection(void)
|
|||
m.m14 = mat[14];
|
||||
m.m15 = mat[15];
|
||||
return m;
|
||||
#else
|
||||
#elif defined(GRAPHICS_API_VULKAN)
|
||||
return RLGL.State.projection;
|
||||
#else // This implies GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 (and not Vulkan)
|
||||
return RLGL.State.projection;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -4714,11 +4910,15 @@ Matrix rlGetMatrixTransform(void)
|
|||
{
|
||||
Matrix mat = rlMatrixIdentity();
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
// TODO: Consider possible transform matrices in the RLGL.State.stack
|
||||
// Is this the right order? or should we start with the first stored matrix instead of the last one?
|
||||
//Matrix matStackTransform = rlMatrixIdentity();
|
||||
//for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = rlMatrixMultiply(RLGL.State.stack[i], matStackTransform);
|
||||
mat = RLGL.State.transform;
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
mat = RLGL.State.transform;
|
||||
#endif
|
||||
#endif
|
||||
return mat;
|
||||
}
|
||||
|
|
@ -4728,7 +4928,11 @@ Matrix rlGetMatrixProjectionStereo(int eye)
|
|||
{
|
||||
Matrix mat = rlMatrixIdentity();
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
mat = RLGL.State.projectionStereo[eye];
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
mat = RLGL.State.projectionStereo[eye];
|
||||
#endif
|
||||
#endif
|
||||
return mat;
|
||||
}
|
||||
|
|
@ -4738,7 +4942,11 @@ Matrix rlGetMatrixViewOffsetStereo(int eye)
|
|||
{
|
||||
Matrix mat = rlMatrixIdentity();
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
mat = RLGL.State.viewOffsetStereo[eye];
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
mat = RLGL.State.viewOffsetStereo[eye];
|
||||
#endif
|
||||
#endif
|
||||
return mat;
|
||||
}
|
||||
|
|
@ -4747,7 +4955,11 @@ Matrix rlGetMatrixViewOffsetStereo(int eye)
|
|||
void rlSetMatrixModelview(Matrix view)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.modelview = view;
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.modelview = view;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -4755,7 +4967,11 @@ void rlSetMatrixModelview(Matrix view)
|
|||
void rlSetMatrixProjection(Matrix projection)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.projection = projection;
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.projection = projection;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -4763,8 +4979,13 @@ void rlSetMatrixProjection(Matrix projection)
|
|||
void rlSetMatrixProjectionStereo(Matrix right, Matrix left)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.projectionStereo[0] = right;
|
||||
RLGL.State.projectionStereo[1] = left;
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.projectionStereo[0] = right;
|
||||
RLGL.State.projectionStereo[1] = left;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -4772,8 +4993,13 @@ void rlSetMatrixProjectionStereo(Matrix right, Matrix left)
|
|||
void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#if !defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.viewOffsetStereo[0] = right;
|
||||
RLGL.State.viewOffsetStereo[1] = left;
|
||||
#else // defined(GRAPHICS_API_VULKAN)
|
||||
RLGL.State.viewOffsetStereo[0] = right;
|
||||
RLGL.State.viewOffsetStereo[1] = left;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue