Refactor (renderer):优化缓冲区上传和渲染管道

- 删除多余的注释并简化applyRenderState逻辑
- 增强了丢失着色器制服和程序的错误记录
改进了绘制调用中的VAO/VBO绑定和属性管理
在渲染系统中增加了高兴功能的加载支持
- 调整线程断言逻辑以更好地处理初始化
- 在缓冲区绑定期间启用顶点属性数组
- 禁用深度测试并启用2D渲染的混合
- 更新了着色器源代码定义和正确的行结束符
- 导出ShaderProgram类以实现DLL可见性
- 通过删除不必要的注释简化纯色着色器
- 集成GLFW窗口管理和OpenGL上下文设置
- 实现了framebuffer resize回调来调整视口
- 添加了基本的渲染循环矩形镶嵌示例
- 确保在退出时正确清理着色器和渲染资源
This commit is contained in:
tzdwindows 7
2025-11-14 22:27:38 +08:00
parent a1e68c878b
commit 0707a6d5cd
7 changed files with 225 additions and 180 deletions

View File

@@ -4,53 +4,202 @@
#ifdef VIVID_2D_MYDLL_API
#undef VIVID_2D_MYDLL_API
#endif
#define VIVID_2D_MYDLL_API __declspec(dllexport)
#define VIVID_2D_MYDLL_API __declspec(dllimport)
#include <glm/glm.hpp>
#include <iostream>
#include <glm/vec2.hpp>
#include <systems/RenderSystem.h>
#include <glad/glad.h>
#include <systems/Buffer/BufferBuilder.h>
#include <systems/Buffer/Tesselator.h>
#include <systems/sources/ShaderManagement.h>
#include <systems/sources/ShaderProgram.h>
#include <GLFW/glfw3.h>
#include <stdexcept>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
RenderSystem::viewport(0, 0, width, height);
}
int main() {
// ----------------------------------------------------
// GLM 向量操作 (与 RenderSystem 无关,保持原样)
// ----------------------------------------------------
glm::vec2 position(100.0f, 200.0f);
glm::vec2 velocity(5.0f, -2.0f);
position += velocity;
std::cout << "New Position: (" << position.x << ", " << position.y << ")" << std::endl;
std::cout << "---------------------------------------" << std::endl;
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// ----------------------------------------------------
// RenderSystem 静态方法调用 (无需实例化)
// ----------------------------------------------------
GLFWwindow* window = glfwCreateWindow(800, 600, "Vivid2D Circle Test", NULL, NULL);
if (window == NULL) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 1. 初始化日志系统 (假设已实现)
std::cout << "Initializing RenderSystem Logging..." << std::endl;
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cerr << "Failed to initialize GLAD" << std::endl;
glfwTerminate();
return -1;
}
RenderSystem::InitializeLogging();
// 2. 开始渲染线程初始化阶段 (假设已实现)
try {
typedef RenderSystem::GLADloader GLADloaderType;
RenderSystem::loadGLFunctions(reinterpret_cast<GLADloaderType>(glfwGetProcAddress));
}
catch (const std::runtime_error& e) {
std::cerr << "FATAL ERROR during GL function loading in DLL: " << e.what() << std::endl;
glfwTerminate();
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
std::cout << "Initializing RenderSystem Logging..." << std::endl;
RenderSystem::initRenderThread();
RenderSystem::beginInitialization();
// 3. 记录一个渲染指令到队列中
std::cout << "Recording a clear color command..." << std::endl;
// 这是一个 lambda 函数,捕获了要执行的 GL 命令
RenderSystem::recordRenderCall([]() {
// 在实际的 RenderSystem 实现中,这会调用 glClearColor(1.0f, 0.5f, 0.0f, 1.0f);
std::cout << "-> (Render Thread) Executing glClearColor(Orange)" << std::endl;
});
RenderSystem::viewport(0, 0, 800, 600);
// 4. 执行队列中的渲染指令
std::cout << "Replaying render queue (" << RenderSystem::getQueueSize() << " calls)..." << std::endl;
RenderSystem::replayQueue(); // 假设这个调用会执行上面的 lambda
// ----------------------------------------------------------------------
// 步骤 1: 记录编译指令,但不立即执行
// ----------------------------------------------------------------------
std::cout << "Compiling all shaders..." << std::endl;
RenderSystem::recordRenderCall([]() { ShaderManagement::compileAllShaders(); });
// ----------------------------------------------------------------------
// 步骤 2: 立即执行队列,编译着色器
// ----------------------------------------------------------------------
std::cout << "Executing initialization queue (Shader compilation)..." << std::endl;
RenderSystem::replayQueue();
std::cout << "Shader compilation executed. Queue size: " << RenderSystem::getQueueSize() << std::endl;
// ----------------------------------------------------------------------
// 步骤 3: 在主线程上安全地获取已编译的着色器 ID 和设置 Uniforms
// ----------------------------------------------------------------------
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, -1.0f, 1.0f);
glm::mat4 viewMatrix = glm::mat4(1.0f);
glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(400.0f, 300.0f, 0.0f));
ShaderProgram* circleProgram = ShaderManagement::getShaderProgram("Solid Color Shader");
if (circleProgram) {
// 记录设置 Uniforms 的指令
RenderSystem::recordRenderCall([=]() {
circleProgram->use();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// 设置 Projection Matrix (mat3)
GLint projLoc = circleProgram->getUniformLocation("uProjectionMatrix");
if (projLoc != -1) {
RenderSystem::uniformMatrix3(projLoc, projection, false);
}
// 设置 View Matrix (mat3)
GLint viewLoc = circleProgram->getUniformLocation("uViewMatrix");
if (viewLoc != -1) {
RenderSystem::uniformMatrix3(viewLoc, viewMatrix, false);
}
// 设置 Model Matrix (mat3)
GLint modelLoc = circleProgram->getUniformLocation("uModelMatrix");
if (modelLoc != -1) {
RenderSystem::uniformMatrix3(modelLoc, modelMatrix, false);
}
circleProgram->stop();
});
}
else {
std::cerr << "FATAL ERROR: Solid Color Shader not found after compilation. Please check the name or compilation logs." << std::endl;
glfwTerminate();
return -1;
}
// ----------------------------------------------------------------------
// 步骤 4: 记录绘制命令,使用已获取的 ID
// ----------------------------------------------------------------------
std::cout << "Recording Circle drawing command..." << std::endl;
// ----------------------------------------------------------------------
// 步骤 5: 执行队列,设置 Uniforms 并记录几何体到 VBO
// ----------------------------------------------------------------------
std::cout << "Executing final initialization queue (Uniforms and Geometry)..." << std::endl;
RenderSystem::replayQueue(); // 再次执行队列,此时执行 Uniform 设置和绘制命令
std::cout << "Final initialization executed. Queue size: " << RenderSystem::getQueueSize() << std::endl;
// 5. 结束初始化阶段
RenderSystem::finishInitialization();
// 6. 关闭日志系统 (确保日志被刷新)
std::cout << "Shutting down RenderSystem Logging." << std::endl;
RenderSystem::ShutdownLogging();
if (RenderSystem::getQueueSize() > 0) {
throw std::runtime_error("FATAL ERROR: Initialization failed to clear the render queue before main loop.");
}
std::cout << "\nStarting main render loop..." << std::endl;
while (!glfwWindowShouldClose(window)) {
RenderSystem::clearColor(0.2f, 0.3f, 0.3f, 1.0f);
RenderSystem::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Buffer::Tesselator& t = Buffer::Tesselator::getInstance();
Buffer::BufferBuilder& builder = t.getBuilder();
// 矩形的位置和大小
const float rectX = 0; // 矩形左上角的 X 坐标
const float rectY = 0; // 矩形左上角的 Y 坐标
const float rectWidth = 200.0f; // 矩形宽度
const float rectHeight = 150.0f; // 矩形高度
// 确保深度测试被禁用,混合被启用
RenderSystem::disableDepthTest();
RenderSystem::enableBlend();
RenderSystem::defaultBlendFunc();
// 【关键修正】:设置绘制模式为实心填充
// 如果你希望画线框,可以使用 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
RenderSystem::recordRenderCall([]() {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // 实心填充模式
});
// 【关键修正】:开始绘制矩形
// 使用 GL_TRIANGLE_STRIP 绘制一个填充的矩形 (4个顶点)
builder.begin(GL_TRIANGLE_STRIP, 4); // 绘制两个三角形形成一个矩形
builder.setShader(circleProgram->getProgramId());
builder.setColor(glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 红色
builder.setTexture(0, 0); // 不需要纹理
// 矩形的四个顶点(顺序很重要,对于 GL_TRIANGLE_STRIP
// 左上角 (X, Y)
builder.vertex(rectX, rectY, 0.0f, 0.0f);
// 右上角 (X + Width, Y)
builder.vertex(rectX + rectWidth, rectY, 1.0f, 0.0f);
// 左下角 (X, Y + Height)
builder.vertex(rectX, rectY + rectHeight, 0.0f, 1.0f);
// 右下角 (X + Width, Y + Height)
builder.vertex(rectX + rectWidth, rectY + rectHeight, 1.0f, 1.0f);
t.end();
// 确保 GL 状态记录被执行
RenderSystem::replayQueue();
glfwSwapBuffers(window);
glfwPollEvents();
}
std::cout << "\nShutting down RenderSystem Logging." << std::endl;
RenderSystem::recordRenderCall([]() { ShaderManagement::cleanup(); });
RenderSystem::replayQueue();
RenderSystem::ShutdownLogging();
return 0;
}

View File

@@ -57,6 +57,14 @@ void RenderSystem::ShutdownLogging() {
}
// ================== <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>̹߳<DFB3><CCB9><EFBFBD> ==================
void RenderSystem::loadGLFunctions(GLADloader loader) {
if (!gladLoadGLLoader((GLADloadproc)loader)) {
s_Logger->critical("Failed to initialize GLAD within RenderSystem DLL!");
// <20>׳<EFBFBD><D7B3><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>
throw std::runtime_error("Failed to load OpenGL functions in DLL.");
}
s_Logger->info("Successfully loaded OpenGL functions in RenderSystem DLL.");
}
void RenderSystem::initRenderThread() {
if (s_RenderThreadId == std::thread::id()) {
s_RenderThreadId = std::this_thread::get_id();
@@ -70,11 +78,19 @@ void RenderSystem::initRenderThread() {
void RenderSystem::beginInitialization() { s_IsInInit = true; }
void RenderSystem::finishInitialization() {
s_IsInInit = false;
if (getQueueSize() > 0) { replayQueue(); }
}
bool RenderSystem::isOnRenderThread() { return std::this_thread::get_id() == s_RenderThreadId; }
bool RenderSystem::isInInitPhase() { return s_IsInInit; }
void RenderSystem::assertOnRenderThread() { if (!isOnRenderThread()) { throw std::runtime_error("RenderSystem called from wrong thread!"); } }
void RenderSystem::assertOnRenderThread() {
if (s_RenderThreadId == std::thread::id()) {
if (!s_IsInInit && !isOnRenderThread()) {
throw std::runtime_error("RenderSystem called from wrong thread!");
}
}
else if (!isOnRenderThread()) {
throw std::runtime_error("RenderSystem called from wrong thread!");
}
}
void RenderSystem::assertOnRenderThreadOrInit() { if (!isInInitPhase() && !isOnRenderThread()) { throw std::runtime_error("RenderSystem called from wrong thread!"); } }
// ================== <20><>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
@@ -159,18 +175,18 @@ void RenderSystem::_viewport(int x, int y, int w, int h) {
}
// ================== VAO / VBO / EBO <20><><EFBFBD><EFBFBD> ==================
GLuint RenderSystem::GenVertexArrays() { assertOnRenderThread(); GLuint vao = 0; glGenVertexArrays(1, &vao); return vao; }
GLuint RenderSystem::GenVertexArrays() { assertOnRenderThreadOrInit(); GLuint vao = 0; glGenVertexArrays(1, &vao); return vao; }
void RenderSystem::DeleteVertexArrays(GLuint vao) { RENDER_SYSTEM_QUEUE_CALL(_glDeleteVertexArrays, vao); }
void RenderSystem::_glDeleteVertexArrays(GLuint v) { assertOnRenderThread(); glDeleteVertexArrays(1, &v); }
void RenderSystem::_glDeleteVertexArrays(GLuint v) { assertOnRenderThreadOrInit(); glDeleteVertexArrays(1, &v); }
void RenderSystem::BindVertexArray(GLuint vao) { RENDER_SYSTEM_QUEUE_CALL(_glBindVertexArray, vao); }
void RenderSystem::_glBindVertexArray(GLuint v) { assertOnRenderThread(); glBindVertexArray(v); }
GLuint RenderSystem::GenBuffers() { assertOnRenderThread(); GLuint buf; glGenBuffers(1, &buf); return buf; }
void RenderSystem::_glBindVertexArray(GLuint v) { assertOnRenderThreadOrInit(); glBindVertexArray(v); }
GLuint RenderSystem::GenBuffers() { assertOnRenderThreadOrInit(); GLuint buf; glGenBuffers(1, &buf); return buf; }
void RenderSystem::DeleteBuffers(GLuint buffer) { RENDER_SYSTEM_QUEUE_CALL(_glDeleteBuffers, buffer); }
void RenderSystem::_glDeleteBuffers(GLuint b) { assertOnRenderThread(); glDeleteBuffers(1, &b); }
void RenderSystem::_glDeleteBuffers(GLuint b) { assertOnRenderThreadOrInit(); glDeleteBuffers(1, &b); }
void RenderSystem::BindBuffer(GLenum target, GLuint buffer) { RENDER_SYSTEM_QUEUE_CALL(_glBindBuffer, target, buffer); }
void RenderSystem::_glBindBuffer(GLenum t, GLuint b) { assertOnRenderThread(); glBindBuffer(t, b); }
void RenderSystem::_glBindBuffer(GLenum t, GLuint b) { assertOnRenderThreadOrInit(); glBindBuffer(t, b); }
void RenderSystem::BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
assertOnRenderThread();
assertOnRenderThreadOrInit();
glBufferData(target, size, data, usage);
}

View File

@@ -24,7 +24,7 @@ public:
~RenderSystem() = delete;
RenderSystem(const RenderSystem&) = delete;
RenderSystem& operator=(const RenderSystem&) = delete;
using GLADloader = void* (*)(const char* name);
// ================== <20><>־ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD> ==================
/**
@@ -45,7 +45,8 @@ public:
static bool isInInitPhase();
static void assertOnRenderThread();
static void assertOnRenderThreadOrInit();
static void loadGLFunctions(GLADloader loader);
// ================== <20><>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ==================
static void recordRenderCall(std::function<void()>&& renderCall);
static void replayQueue();

View File

@@ -9,17 +9,14 @@
namespace Buffer {
void BufferUploader::applyRenderState(const RenderState& state) {
// 1. Ӧ<><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (state.textureId != 0) {
RenderSystem::activeTexture(GL_TEXTURE0 + state.textureUnit);
RenderSystem::bindTexture(state.textureId);
}
// 2. Ӧ<><D3A6><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB>
unsigned int currentProgram = 0;
if (state.shaderProgram != 0) {
currentProgram = state.shaderProgram;
RenderSystem::useProgram(state.shaderProgram);
RenderSystem::useProgram(state.shaderProgram); // <--- <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD> Program
}
else {
// <20><><EFBFBD><EFBFBD>״̬<D7B4><CCAC>û<EFBFBD><C3BB>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>󶨵<EFBFBD><F3B6A8B5><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@@ -27,19 +24,18 @@ namespace Buffer {
glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
currentProgram = static_cast<unsigned int>(programId);
}
// 3. <20><><EFBFBD><EFBFBD> uColor Uniform (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Program ʱ<><CAB1><EFBFBD><EFBFBD>)
if (currentProgram != 0) {
GLint colorLoc = RenderSystem::getUniformLocation(currentProgram, "uColor");
if (colorLoc != -1) {
// ʹ<><CAB9> RenderSystem::uniform4f <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
RenderSystem::uniform4f(colorLoc,
state.color.x, state.color.y, state.color.z, state.color.w);
}
else {
spdlog::warn("BufferUploader::applyRenderState: Uniform 'uColor' not found in program ID: {}.", currentProgram);
}
}
else {
spdlog::debug("BufferUploader::applyRenderState: No shader program available for color setting.");
spdlog::warn("BufferUploader::applyRenderState: No shader program available for color setting.");
}
// 4. Ӧ<>û<EFBFBD><C3BB><EFBFBD>ģʽ
@@ -62,7 +58,6 @@ namespace Buffer {
}
void BufferUploader::restoreRenderState(const RenderState& previousState) {
// <20>ָ<EFBFBD>֮ǰ<D6AE><C7B0>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> RenderState::applyState() <20><>ʵ<EFBFBD>֡<EFBFBD>
previousState.applyState();
}
@@ -72,28 +67,28 @@ namespace Buffer {
// ==========================================================
void BufferUploader::drawWithShader(std::unique_ptr<BuiltBuffer> buffer) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>գ<EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
if (!buffer) return;
RenderSystem::assertOnRenderThread();
RenderState currentState;
currentState.saveCurrentState();
try {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> -> <20><><EFBFBD><EFBFBD> unique_ptr ָ<><D6B8><EFBFBD><EFBFBD> BuiltBuffer <20><>Ա
const RenderState& bufferState = buffer->renderState;
applyRenderState(bufferState);
if (buffer->vao != 0) {
if (buffer->vao != 0 && buffer->vbo != 0) {
RenderSystem::BindVertexArray(buffer->vao);
RenderSystem::BindBuffer(GL_ARRAY_BUFFER, buffer->vbo);
RenderSystem::enableVertexAttribArray(0);
RenderSystem::enableVertexAttribArray(1);
}
if (buffer->vertexCount > 0) {
RenderSystem::drawArrays(buffer->mode, 0, buffer->vertexCount);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VAO
if (buffer->vao != 0) {
RenderSystem::disableVertexAttribArray(0);
RenderSystem::disableVertexAttribArray(1);
RenderSystem::BindBuffer(GL_ARRAY_BUFFER, 0);
RenderSystem::BindVertexArray(0);
}
}

View File

@@ -11,7 +11,7 @@
* * <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E0A3AC><EFBFBD>ڹ<EFBFBD><DAB9><EFBFBD>OpenGL<47><4C>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>򣬰<EFBFBD><F2A3ACB0><EFBFBD>ͳһ<CDB3><D2BB><EFBFBD><EFBFBD>(uniform)<29><><EFBFBD><EFBFBD><EFBFBD>úͻ<C3BA><CDBB>
* <20><><EFBFBD>ǵ<EFBFBD><C7B5>̳<EFBFBD><CCB3>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><E9BAAF><EFBFBD><EFBFBD>
*/
class ShaderProgram
class VIVID_2D_MYDLL_API ShaderProgram
{
public:
// <20><><EFBFBD><EFBFBD><ECBAAF>

View File

@@ -1,123 +1,12 @@
#include "pch.h"
#include "pch.h"
#include "Shader2D.h"
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD> GLSL <20><><EFBFBD><EFBFBD> (<28><>Ӧ VertexShaders.java)
static const std::string VERTEX_SHADER_SRC = R"""(
#version 330 core
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
out vec2 vTexCoord;
out vec2 vWorldPos;
uniform mat3 uModelMatrix;
uniform mat3 uViewMatrix;
uniform mat3 uProjectionMatrix;
void main() {
// ʹ<><CAB9> 3x3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļλ<C4BB><CEBB>
vec3 p = uProjectionMatrix * uViewMatrix * uModelMatrix * vec3(aPosition, 1.0);
gl_Position = vec4(p.xy, 0.0, 1.0);
vTexCoord = aTexCoord;
// <20><><EFBFBD><EFBFBD> world-space λ<>ù<EFBFBD> fragment shader ʹ<>ã<EFBFBD><C3A3><EFBFBD> xy<78><79>
vWorldPos = (uModelMatrix * vec3(aPosition, 1.0)).xy;
}
)""";
// Ƭ<><C6AC><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB> GLSL <20><><EFBFBD><EFBFBD> (<28><>Ӧ FragmentShaders.java)
static const std::string FRAGMENT_SHADER_SRC = R"""(
#version 330 core
in vec2 vTexCoord;
in vec2 vWorldPos;
out vec4 FragColor;
uniform sampler2D uTexture;
uniform vec4 uColor;
uniform float uOpacity;
uniform int uBlendMode;
uniform int uDebugMode;
#define MAX_LIGHTS 8
uniform vec2 uLightsPos[MAX_LIGHTS];
uniform vec3 uLightsColor[MAX_LIGHTS];
uniform float uLightsIntensity[MAX_LIGHTS];
uniform int uLightsIsAmbient[MAX_LIGHTS];
uniform int uLightCount;
// <20><><EFBFBD><EFBFBD>˥<EFBFBD><CBA5>ϵ<EFBFBD><CFB5>
const float ATT_CONST = 1.0;
const float ATT_LINEAR = 0.09;
const float ATT_QUAD = 0.032;
void main() {
// 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>
vec4 tex = texture(uTexture, vTexCoord);
float alpha = tex.a * uOpacity;
if (alpha <= 0.001) discard;
// 2. <20>޹<EFBFBD>Դ<EFBFBD>Ż<EFBFBD>·<EFBFBD><C2B7>
if (uLightCount == 0) {
vec3 base = tex.rgb * uColor.rgb;
base = clamp(base, 0.0, 1.0);
FragColor = vec4(base, alpha);
return;
}
// 3. <20><><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>·<EFBFBD><C2B7>
vec3 baseColor = tex.rgb * uColor.rgb;
vec3 ambient = vec3(0.06); // С<><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E2B2B9>
vec3 lighting = vec3(0.0);
vec3 specularAccum = vec3(0.0);
// <20>ۻ<EFBFBD><DBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < uLightCount; ++i) {
if (uLightsIsAmbient[i] == 1) {
lighting += uLightsColor[i] * uLightsIntensity[i];
}
}
lighting += ambient;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ/<2F>ǻ<EFBFBD><C7BB><EFBFBD><EFBFBD><EFBFBD>
for (int i = 0; i < uLightCount; ++i) {
if (uLightsIsAmbient[i] == 1) continue;
vec2 toLight = uLightsPos[i] - vWorldPos;
float dist = length(toLight);
// <20><>׼˥<D7BC><CBA5>
float attenuation = ATT_CONST / (ATT_CONST + ATT_LINEAR * dist + ATT_QUAD * dist * dist);
float radiance = uLightsIntensity[i] * attenuation;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD>ھ<EFBFBD><DABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
float diffuseFactor = clamp(1.0 - (dist * 0.0015), 0.0, 1.0);
vec3 diff = uLightsColor[i] * radiance * diffuseFactor;
lighting += diff;
// <20>򵥸߹<F2B5A5B8>
vec3 lightDir3 = normalize(vec3(toLight, 0.0));
vec3 viewDir = vec3(0.0, 0.0, 1.0);
vec3 normal = vec3(0.0, 0.0, 1.0);
vec3 reflectDir = reflect(-lightDir3, normal);
float specFactor = pow(max(dot(viewDir, reflectDir), 0.0), 16.0);
float specIntensity = 0.2;
specularAccum += uLightsColor[i] * radiance * specFactor * specIntensity;
}
// Ӧ<>ù<EFBFBD><C3B9><EFBFBD>
vec3 totalLighting = min(lighting + specularAccum, vec3(2.0));
vec3 finalColor = baseColor * totalLighting;
// 4. <20>򵥻<EFBFBD><F2B5A5BB><EFBFBD>ģʽ
if (uBlendMode == 1) finalColor = tex.rgb + uColor.rgb;
else if (uBlendMode == 2) finalColor = tex.rgb * uColor.rgb;
else if (uBlendMode == 3) finalColor = 1.0 - (1.0 - tex.rgb) * (1.0 - uColor.rgb);
// 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
finalColor = clamp(finalColor, 0.0, 1.0);
FragColor = vec4(finalColor, alpha);
}
)""";
// 顶点着色器 GLSL 代码 (对应 VertexShaders.java)
static const std::string VERTEX_SHADER_SRC = "\r\n#version 330 core\r\nlayout(location = 0) in vec2 aPosition;\r\nlayout(location = 1) in vec2 aTexCoord;\r\nout vec2 vTexCoord;\r\nout vec2 vWorldPos;\r\n\r\nuniform mat3 uModelMatrix;\r\nuniform mat3 uViewMatrix;\r\nuniform mat3 uProjectionMatrix;\r\n\r\nvoid main() {\r\n vec3 p = uProjectionMatrix * uViewMatrix * uModelMatrix * vec3(aPosition, 1.0);\r\n gl_Position = vec4(p.xy, 0.0, 1.0);\r\n vTexCoord = aTexCoord;\r\n vWorldPos = (uModelMatrix * vec3(aPosition, 1.0)).xy;\r\n}\r\n";
// 片段着色器 GLSL 代码 (对应 FragmentShaders.java)
static const std::string FRAGMENT_SHADER_SRC = "\r\n#version 330 core\r\nin vec2 vTexCoord;\r\nin vec2 vWorldPos;\r\nout vec4 FragColor;\r\n\r\nuniform sampler2D uTexture;\r\nuniform vec4 uColor;\r\nuniform float uOpacity;\r\nuniform int uBlendMode;\r\nuniform int uDebugMode;\r\n\r\n#define MAX_LIGHTS 8\r\nuniform vec2 uLightsPos[MAX_LIGHTS];\r\nuniform vec3 uLightsColor[MAX_LIGHTS];\r\nuniform float uLightsIntensity[MAX_LIGHTS];\r\nuniform int uLightsIsAmbient[MAX_LIGHTS];\r\nuniform int uLightCount;\r\n\r\nconst float ATT_CONST = 1.0;\r\nconst float ATT_LINEAR = 0.09;\r\nconst float ATT_QUAD = 0.032;\r\n\r\nvoid main() {\r\n int i;\r\n\r\n vec4 tex = texture(uTexture, vTexCoord);\r\n float alpha = tex.a * uOpacity;\r\n if (alpha <= 0.001) discard;\r\n\r\n if (uLightCount == 0) {\r\n vec3 base = tex.rgb * uColor.rgb;\r\n base = clamp(base, 0.0, 1.0);\r\n FragColor = vec4(base, alpha);\r\n return;\r\n }\r\n\r\n vec3 baseColor = tex.rgb * uColor.rgb;\r\n vec3 ambient = vec3(0.06);\r\n vec3 lighting = vec3(0.0);\r\n vec3 specularAccum = vec3(0.0);\r\n\r\n for (i = 0; i < uLightCount; ++i) {\r\n if (uLightsIsAmbient[i] == 1) {\r\n lighting += uLightsColor[i] * uLightsIntensity[i];\r\n }\r\n }\r\n lighting += ambient;\r\n\r\n for (i = 0; i < uLightCount; ++i) {\r\n if (uLightsIsAmbient[i] == 1) continue;\r\n\r\n vec2 toLight = uLightsPos[i] - vWorldPos;\r\n float dist = length(toLight);\r\n float attenuation = ATT_CONST / (ATT_CONST + ATT_LINEAR * dist + ATT_QUAD * dist * dist);\r\n\r\n float radiance = uLightsIntensity[i] * attenuation;\r\n\r\n float diffuseFactor = clamp(1.0 - (dist * 0.0015), 0.0, 1.0); \r\n vec3 diff = uLightsColor[i] * radiance * diffuseFactor;\r\n lighting += diff;\r\n\r\n vec3 lightDir3 = normalize(vec3(toLight, 0.0));\r\n vec3 viewDir = vec3(0.0, 0.0, 1.0);\r\n vec3 normal = vec3(0.0, 0.0, 1.0);\r\n vec3 reflectDir = reflect(-lightDir3, normal);\r\n float specFactor = pow(max(dot(viewDir, reflectDir), 0.0), 16.0); \r\n float specIntensity = 0.2; \r\n specularAccum += uLightsColor[i] * radiance * specFactor * specIntensity;\r\n }\r\n\r\n vec3 totalLighting = min(lighting + specularAccum, vec3(2.0));\r\n vec3 finalColor = baseColor * totalLighting;\r\n\r\n if (uBlendMode == 1) finalColor = tex.rgb + uColor.rgb;\r\n else if (uBlendMode == 2) finalColor = tex.rgb * uColor.rgb;\r\n else if (uBlendMode == 3) finalColor = 1.0 - (1.0 - tex.rgb) * (1.0 - uColor.rgb);\r\n\r\n finalColor = clamp(finalColor, 0.0, 1.0);\r\n FragColor = vec4(finalColor, alpha);\r\n}\r\n";
class Shader2D::VertexShaders final : public Shader {
public:

View File

@@ -14,7 +14,6 @@ uniform mat3 uViewMatrix;
uniform mat3 uProjectionMatrix;
void main() {
// ʹ<><CAB9> 3x3 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļλ<C4BB><CEBB>
vec3 p = uProjectionMatrix * uViewMatrix * uModelMatrix * vec3(aPosition, 1.0);
gl_Position = vec4(p.xy, 0.0, 1.0);
}
@@ -28,13 +27,9 @@ uniform vec4 uColor;
uniform float uOpacity;
void main() {
// ֱ<><D6B1>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
vec4 finalColor = uColor;
finalColor.a *= uOpacity;
// <20><><EFBFBD><EFBFBD>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>̫<EFBFBD><CCAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƭ<EFBFBD><C6AC>
if (finalColor.a <= 0.001) discard;
FragColor = finalColor;
}
)""";