feat(render): 添加光源与物理系统支持
- 新增 BufferBuilder 工具类用于简化顶点数据提交 - 实现 LightSource 和 LightSourceData 类以支持光源管理- 在 Model2D 中集成光源系统,支持序列化与反序列化 - 扩展 ModelData 以支持物理系统数据的完整序列化 - 重构 ModelRender以支持物理系统应用及碰撞箱渲染 - 添加粒子、弹簧、约束与碰撞体的数据结构与序列化逻辑 - 实现变形器的序列化接口以支持参数驱动动画的持久化
This commit is contained in:
@@ -2,17 +2,19 @@ package com.chuangzhou.vivid2D.render;
|
||||
|
||||
import com.chuangzhou.vivid2D.render.model.Model2D;
|
||||
import com.chuangzhou.vivid2D.render.model.ModelPart;
|
||||
import com.chuangzhou.vivid2D.render.model.util.LightSource;
|
||||
import com.chuangzhou.vivid2D.render.model.util.Mesh2D;
|
||||
import com.chuangzhou.vivid2D.render.model.util.PhysicsSystem; // 引入 PhysicsSystem
|
||||
import com.chuangzhou.vivid2D.render.model.util.Texture;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.*;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -20,6 +22,7 @@ import static org.lwjgl.opengl.GL20.glGetUniformLocation;
|
||||
|
||||
/**
|
||||
* 重构后的 ModelRender:更模块化、健壮的渲染子系统
|
||||
* (已修改以应用物理系统,并支持渲染碰撞箱)
|
||||
* @author tzdwindows 7
|
||||
*/
|
||||
public final class ModelRender {
|
||||
@@ -44,6 +47,18 @@ public final class ModelRender {
|
||||
// 默认白色纹理
|
||||
private static int defaultTextureId = 0;
|
||||
|
||||
// ================== 碰撞箱渲染配置 ==================
|
||||
// 是否在渲染时绘制碰撞箱(线框)
|
||||
public static boolean renderColliders = false;
|
||||
// 碰撞箱线宽
|
||||
public static float colliderLineWidth = 2.0f;
|
||||
// 碰撞箱颜色(默认白色)
|
||||
public static Vector4f colliderColor = new Vector4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
// 圆形碰撞体绘制细分(越高越圆)
|
||||
private static final int CIRCLE_SEGMENTS = 32;
|
||||
// 是否在渲染时绘制碰撞箱
|
||||
public static boolean renderLightPositions = true;
|
||||
|
||||
// ================== 内部类:ShaderProgram ==================
|
||||
private static class ShaderProgram {
|
||||
final int programId;
|
||||
@@ -96,46 +111,84 @@ public final class ModelRender {
|
||||
// ================== 着色器源 ==================
|
||||
private static final String VERTEX_SHADER_SRC =
|
||||
"""
|
||||
#version 330 core
|
||||
layout(location = 0) in vec2 aPosition;
|
||||
layout(location = 1) in vec2 aTexCoord;
|
||||
out vec2 vTexCoord;
|
||||
out vec2 vDebugPos;
|
||||
uniform mat3 uModelMatrix;
|
||||
uniform mat3 uViewMatrix;
|
||||
uniform mat3 uProjectionMatrix;
|
||||
void main() {
|
||||
vec3 p = uProjectionMatrix * uViewMatrix * uModelMatrix * vec3(aPosition, 1.0);
|
||||
gl_Position = vec4(p.xy, 0.0, 1.0);
|
||||
vTexCoord = aTexCoord;
|
||||
vDebugPos = p.xy;
|
||||
}""";
|
||||
#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() {
|
||||
vec3 p = uProjectionMatrix * uViewMatrix * uModelMatrix * vec3(aPosition, 1.0);
|
||||
gl_Position = vec4(p.xy, 0.0, 1.0);
|
||||
vTexCoord = aTexCoord;
|
||||
vWorldPos = (uModelMatrix * vec3(aPosition, 1.0)).xy;
|
||||
}
|
||||
""";
|
||||
|
||||
private static final String FRAGMENT_SHADER_SRC =
|
||||
"""
|
||||
#version 330 core
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vDebugPos;
|
||||
out vec4 FragColor;
|
||||
uniform sampler2D uTexture;
|
||||
uniform vec4 uColor;
|
||||
uniform float uOpacity;
|
||||
uniform int uBlendMode;
|
||||
uniform int uDebugMode;
|
||||
void main() {
|
||||
if (uDebugMode == 1) {
|
||||
FragColor = vec4(vDebugPos * 0.5 + 0.5, 0.0, 1.0);
|
||||
return;
|
||||
}
|
||||
vec4 tex = texture(uTexture, vTexCoord);
|
||||
vec4 finalColor = tex * uColor;
|
||||
if (uBlendMode == 1) finalColor.rgb = tex.rgb + uColor.rgb;
|
||||
else if (uBlendMode == 2) finalColor.rgb = tex.rgb * uColor.rgb;
|
||||
else if (uBlendMode == 3) finalColor.rgb = 1.0 - (1.0 - tex.rgb) * (1.0 - uColor.rgb);
|
||||
finalColor.a = tex.a * uOpacity;
|
||||
if (finalColor.a <= 0.001) discard;
|
||||
FragColor = finalColor;
|
||||
}""";
|
||||
#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;
|
||||
|
||||
void main() {
|
||||
if (uDebugMode == 1) {
|
||||
FragColor = vec4(vWorldPos * 0.5 + 0.5, 0.0, 1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 tex = texture(uTexture, vTexCoord);
|
||||
vec3 finalColor = tex.rgb * uColor.rgb;
|
||||
vec3 lighting = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < uLightCount; i++) {
|
||||
if (uLightsIsAmbient[i] == 1) {
|
||||
lighting += uLightsColor[i] * uLightsIntensity[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < uLightCount; i++) {
|
||||
if (uLightsIsAmbient[i] == 1) continue;
|
||||
|
||||
float intensity = uLightsIntensity[i];
|
||||
if (intensity <= 0.0) continue;
|
||||
|
||||
vec2 lightDir = uLightsPos[i] - vWorldPos;
|
||||
float dist = length(lightDir);
|
||||
float atten = 1.0 / (1.0 + 0.1 * dist + 0.01 * dist * dist);
|
||||
lighting += uLightsColor[i] * intensity * atten;
|
||||
}
|
||||
|
||||
finalColor *= min(lighting, vec3(2.0));
|
||||
|
||||
if (uBlendMode == 1) finalColor.rgb = tex.rgb + uColor.rgb;
|
||||
else if (uBlendMode == 2) finalColor.rgb = tex.rgb * uColor.rgb;
|
||||
else if (uBlendMode == 3) finalColor.rgb = 1.0 - (1.0 - tex.rgb) * (1.0 - uColor.rgb);
|
||||
|
||||
float alpha = tex.a * uOpacity;
|
||||
if (alpha <= 0.001) discard;
|
||||
|
||||
FragColor = vec4(finalColor, alpha);
|
||||
}
|
||||
""";
|
||||
|
||||
// ================== 初始化 / 清理 ==================
|
||||
public static synchronized void initialize() {
|
||||
@@ -174,6 +227,35 @@ public final class ModelRender {
|
||||
System.out.println("GLSL Version: " + GL20.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION));
|
||||
}
|
||||
|
||||
private static void uploadLightsToShader(ShaderProgram sp, Model2D model) {
|
||||
List<LightSource> lights = model.getLights();
|
||||
int lightCount = Math.min(lights.size(), 8);
|
||||
|
||||
// 设置光源数量
|
||||
setUniformIntInternal(sp, "uLightCount", lightCount);
|
||||
|
||||
for (int i = 0; i < lightCount; i++) {
|
||||
LightSource l = lights.get(i);
|
||||
if (!l.isEnabled()) continue;
|
||||
|
||||
// 设置光源位置(环境光位置设为0)
|
||||
Vector2f pos = l.isAmbient() ? new Vector2f(0, 0) : l.getPosition();
|
||||
setUniformVec2Internal(sp, "uLightsPos[" + i + "]", pos);
|
||||
|
||||
setUniformVec3Internal(sp, "uLightsColor[" + i + "]", l.getColor());
|
||||
setUniformFloatInternal(sp, "uLightsIntensity[" + i + "]", l.getIntensity());
|
||||
|
||||
// 设置是否为环境光
|
||||
setUniformIntInternal(sp, "uLightsIsAmbient[" + i + "]", l.isAmbient() ? 1 : 0);
|
||||
}
|
||||
|
||||
// 禁用未使用的光源
|
||||
for (int i = lightCount; i < 8; i++) {
|
||||
setUniformFloatInternal(sp, "uLightsIntensity[" + i + "]", 0f);
|
||||
setUniformIntInternal(sp, "uLightsIsAmbient[" + i + "]", 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setupGLState() {
|
||||
GL11.glClearColor(CLEAR_COLOR.x, CLEAR_COLOR.y, CLEAR_COLOR.z, CLEAR_COLOR.w);
|
||||
|
||||
@@ -204,12 +286,13 @@ public final class ModelRender {
|
||||
shaderMap.put("default", sp);
|
||||
defaultProgram = sp;
|
||||
|
||||
// 设置一些默认 uniform(需要先 use)
|
||||
sp.use();
|
||||
setUniformIntInternal(sp, "uTexture", 0);
|
||||
setUniformFloatInternal(sp, "uOpacity", 1.0f);
|
||||
setUniformVec4Internal(sp, "uColor", new Vector4f(1,1,1,1));
|
||||
setUniformIntInternal(sp, "uBlendMode", 0);
|
||||
setUniformIntInternal(sp, "uDebugMode", 0);
|
||||
setUniformIntInternal(sp, "uLightCount", 0); // 默认没有光源
|
||||
sp.stop();
|
||||
}
|
||||
|
||||
@@ -284,38 +367,70 @@ public final class ModelRender {
|
||||
System.out.println("ModelRender cleaned up");
|
||||
}
|
||||
|
||||
// ================== 渲染流程 ==================
|
||||
// ================== 渲染流程 (已修改) ==================
|
||||
public static void render(float deltaTime, Model2D model) {
|
||||
if (!initialized) throw new IllegalStateException("ModelRender not initialized");
|
||||
if (model == null) return;
|
||||
|
||||
// 更新模型(确保 worldTransform 已经被计算)
|
||||
// 物理系统更新
|
||||
PhysicsSystem physics = model.getPhysics();
|
||||
if (physics != null && physics.isEnabled()) {
|
||||
physics.update(deltaTime, model);
|
||||
}
|
||||
|
||||
model.update(deltaTime);
|
||||
|
||||
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | (enableDepthTest ? GL11.GL_DEPTH_BUFFER_BIT : 0));
|
||||
|
||||
// 使用默认 shader(保持绑定直到完成渲染)
|
||||
defaultProgram.use();
|
||||
|
||||
// setUniformIntInternal(defaultProgram, "uDebugMode", 0); 设置debug模式
|
||||
|
||||
// 设置投影与视图(3x3 正交投影用于 2D)
|
||||
// 设置投影与视图
|
||||
Matrix3f proj = buildOrthoProjection(viewportWidth, viewportHeight);
|
||||
setUniformMatrix3(defaultProgram, "uProjectionMatrix", proj);
|
||||
setUniformMatrix3(defaultProgram, "uViewMatrix", new Matrix3f().identity());
|
||||
|
||||
// 递归渲染所有根部件(使用 3x3 矩阵)
|
||||
// 添加光源数据上传
|
||||
uploadLightsToShader(defaultProgram, model);
|
||||
renderLightPositions(model);
|
||||
|
||||
// 递归渲染所有根部件
|
||||
Matrix3f identity = new Matrix3f().identity();
|
||||
for (ModelPart p : model.getParts()) {
|
||||
if (p.getParent() != null) continue;
|
||||
renderPartRecursive(p, identity);
|
||||
}
|
||||
|
||||
defaultProgram.stop();
|
||||
if (renderColliders && physics != null) {
|
||||
renderPhysicsColliders(physics);
|
||||
}
|
||||
|
||||
|
||||
|
||||
defaultProgram.stop();
|
||||
checkGLError("render");
|
||||
}
|
||||
|
||||
private static void renderLightPositions(Model2D model) {
|
||||
if (!renderLightPositions) return;
|
||||
|
||||
GL11.glPointSize(10.0f);
|
||||
setUniformIntInternal(defaultProgram, "uDebugMode", 1);
|
||||
|
||||
for (LightSource light : model.getLights()) {
|
||||
if (!light.isEnabled()) continue;
|
||||
|
||||
// 绘制光源位置
|
||||
com.chuangzhou.vivid2D.render.util.BufferBuilder bb =
|
||||
new com.chuangzhou.vivid2D.render.util.BufferBuilder(1 * 4);
|
||||
bb.begin(GL11.GL_POINTS, 1);
|
||||
bb.vertex(light.getPosition().x, light.getPosition().y, 0.5f, 0.5f);
|
||||
bb.end();
|
||||
}
|
||||
|
||||
setUniformIntInternal(defaultProgram, "uDebugMode", 0);
|
||||
GL11.glPointSize(1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关键修改点:在渲染前确保更新 part 的 worldTransform,
|
||||
* 然后直接使用 part.getWorldTransform() 作为 uModelMatrix 传入 shader。
|
||||
@@ -330,9 +445,8 @@ public final class ModelRender {
|
||||
// 先设置部件相关的 uniform(opacity / blendMode / color 等)
|
||||
setPartUniforms(defaultProgram, part);
|
||||
|
||||
// 把 world 矩阵传给 shader(兼容 uModelMatrix 和 可能的 uModel)
|
||||
// 把 world 矩阵传给 shader(uModelMatrix)
|
||||
setUniformMatrix3(defaultProgram, "uModelMatrix", world);
|
||||
setUniformMatrix3(defaultProgram, "uModel", world);
|
||||
|
||||
// 绘制本节点的所有 mesh(将 world 传入 renderMesh)
|
||||
for (Mesh2D mesh : part.getMeshes()) {
|
||||
@@ -348,9 +462,6 @@ public final class ModelRender {
|
||||
private static void renderMesh(Mesh2D mesh, Matrix3f modelMatrix) {
|
||||
if (!mesh.isVisible()) return;
|
||||
|
||||
// 使用默认 shader
|
||||
defaultProgram.use();
|
||||
|
||||
// 如果 mesh 已经被烘焙到世界坐标,则传 identity 矩阵给 shader(防止重复变换)
|
||||
Matrix3f matToUse = mesh.isBakedToWorld() ? new Matrix3f().identity() : modelMatrix;
|
||||
|
||||
@@ -364,27 +475,124 @@ public final class ModelRender {
|
||||
setUniformIntInternal(defaultProgram, "uTexture", 0);
|
||||
}
|
||||
|
||||
// 将模型矩阵设置为当前 mesh 使用的矩阵(shader 内名为 uModelMatrix)
|
||||
setUniformMatrix3(defaultProgram, "uModelMatrix", matToUse);
|
||||
|
||||
// 调用 Mesh2D 的 draw 方法,传入当前使用的着色器程序和变换矩阵
|
||||
mesh.draw(defaultProgram.programId, matToUse);
|
||||
|
||||
checkGLError("renderMesh");
|
||||
}
|
||||
|
||||
// ================== 渲染碰撞箱相关实现 ==================
|
||||
|
||||
private static int getGLDrawMode(int meshDrawMode) {
|
||||
switch (meshDrawMode) {
|
||||
case Mesh2D.POINTS: return GL11.GL_POINTS;
|
||||
case Mesh2D.LINES: return GL11.GL_LINES;
|
||||
case Mesh2D.LINE_STRIP: return GL11.GL_LINE_STRIP;
|
||||
case Mesh2D.TRIANGLES: return GL11.GL_TRIANGLES;
|
||||
case Mesh2D.TRIANGLE_STRIP: return GL11.GL_TRIANGLE_STRIP;
|
||||
case Mesh2D.TRIANGLE_FAN: return GL11.GL_TRIANGLE_FAN;
|
||||
default: return GL11.GL_TRIANGLES;
|
||||
private static void renderPhysicsColliders(PhysicsSystem physics) {
|
||||
// 设置渲染状态
|
||||
GL11.glLineWidth(colliderLineWidth);
|
||||
|
||||
// 绑定默认纹理(shader 依赖 uTexture)并设置颜色/opacity
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, defaultTextureId);
|
||||
setUniformIntInternal(defaultProgram, "uTexture", 0);
|
||||
setUniformVec4Internal(defaultProgram, "uColor", colliderColor);
|
||||
setUniformFloatInternal(defaultProgram, "uOpacity", 1.0f);
|
||||
setUniformIntInternal(defaultProgram, "uBlendMode", 0);
|
||||
setUniformIntInternal(defaultProgram, "uDebugMode", 0);
|
||||
|
||||
// 使用单位矩阵作为 model(碰撞体顶点按世界坐标提供)
|
||||
setUniformMatrix3(defaultProgram, "uModelMatrix", new Matrix3f().identity());
|
||||
|
||||
for (PhysicsSystem.PhysicsCollider collider : physics.getColliders()) {
|
||||
if (!collider.isEnabled()) continue;
|
||||
|
||||
if (collider instanceof PhysicsSystem.CircleCollider) {
|
||||
PhysicsSystem.CircleCollider c = (PhysicsSystem.CircleCollider) collider;
|
||||
drawCircleColliderWire(c.getCenter(), c.getRadius());
|
||||
} else if (collider instanceof PhysicsSystem.RectangleCollider) {
|
||||
PhysicsSystem.RectangleCollider r = (PhysicsSystem.RectangleCollider) collider;
|
||||
drawRectangleColliderWire(r.getCenter(), r.getWidth(), r.getHeight());
|
||||
} else {
|
||||
// 未知类型:尝试调用 collidesWith 以获取位置(跳过)
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复默认线宽
|
||||
GL11.glLineWidth(1.0f);
|
||||
}
|
||||
|
||||
// ================== 上传数据 ==================(被弃用)
|
||||
|
||||
/**
|
||||
* 绘制圆形碰撞框(线框)
|
||||
* 使用临时 VAO/VBO,每帧创建并删除(简单实现)
|
||||
*/
|
||||
private static void drawCircleColliderWire(Vector2f center, float radius) {
|
||||
int segments = Math.max(8, CIRCLE_SEGMENTS);
|
||||
com.chuangzhou.vivid2D.render.util.BufferBuilder bb = new com.chuangzhou.vivid2D.render.util.BufferBuilder(segments * 4);
|
||||
bb.begin(GL11.GL_LINE_LOOP, segments);
|
||||
for (int i = 0; i < segments; i++) {
|
||||
double ang = 2.0 * Math.PI * i / segments;
|
||||
float x = center.x + radius * (float) Math.cos(ang);
|
||||
float y = center.y + radius * (float) Math.sin(ang);
|
||||
// 给常量 texcoord
|
||||
bb.vertex(x, y, 0.5f, 0.5f);
|
||||
}
|
||||
bb.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制矩形碰撞框(线框)
|
||||
*/
|
||||
private static void drawRectangleColliderWire(Vector2f center, float width, float height) {
|
||||
float halfW = width / 2.0f;
|
||||
float halfH = height / 2.0f;
|
||||
com.chuangzhou.vivid2D.render.util.BufferBuilder bb = new com.chuangzhou.vivid2D.render.util.BufferBuilder(4 * 4);
|
||||
bb.begin(GL11.GL_LINE_LOOP, 4);
|
||||
bb.vertex(center.x - halfW, center.y - halfH, 0.5f, 0.5f);
|
||||
bb.vertex(center.x + halfW, center.y - halfH, 0.5f, 0.5f);
|
||||
bb.vertex(center.x + halfW, center.y + halfH, 0.5f, 0.5f);
|
||||
bb.vertex(center.x - halfW, center.y + halfH, 0.5f, 0.5f);
|
||||
bb.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 float[] (x,y,u,v interleaved) 绘制 GL_LINE_LOOP
|
||||
*/
|
||||
private static void drawLineLoopFromFloatArray(float[] interleavedXYUV, int vertexCount) {
|
||||
// 创建 VAO/VBO
|
||||
int vao = GL30.glGenVertexArrays();
|
||||
int vbo = GL15.glGenBuffers();
|
||||
|
||||
GL30.glBindVertexArray(vao);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
// 上传数据
|
||||
FloatBuffer fb = MemoryUtil.memAllocFloat(interleavedXYUV.length);
|
||||
fb.put(interleavedXYUV).flip();
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, fb, GL15.GL_DYNAMIC_DRAW);
|
||||
MemoryUtil.memFree(fb);
|
||||
|
||||
// attrib 0 -> aPosition (vec2)
|
||||
GL20.glEnableVertexAttribArray(0);
|
||||
GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 4 * Float.BYTES, 0);
|
||||
|
||||
// attrib 1 -> aTexCoord (vec2) (提供常量 texcoord)
|
||||
GL20.glEnableVertexAttribArray(1);
|
||||
GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, 4 * Float.BYTES, 2 * Float.BYTES);
|
||||
|
||||
// 绘制线环
|
||||
GL11.glDrawArrays(GL11.GL_LINE_LOOP, 0, vertexCount);
|
||||
|
||||
// 清理
|
||||
GL20.glDisableVertexAttribArray(0);
|
||||
GL20.glDisableVertexAttribArray(1);
|
||||
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GL30.glBindVertexArray(0);
|
||||
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GL30.glDeleteVertexArrays(vao);
|
||||
|
||||
checkGLError("drawLineLoopFromFloatArray");
|
||||
}
|
||||
|
||||
// ================== uniform 设置辅助(内部使用,确保 program 已绑定) ==================
|
||||
private static void setUniformIntInternal(ShaderProgram sp, String name, int value) {
|
||||
@@ -392,6 +600,20 @@ public final class ModelRender {
|
||||
if (loc != -1) GL20.glUniform1i(loc, value);
|
||||
}
|
||||
|
||||
private static void setUniformVec3Internal(ShaderProgram sp, String name, org.joml.Vector3f vec) {
|
||||
int loc = sp.getUniformLocation(name);
|
||||
if (loc != -1) {
|
||||
GL20.glUniform3f(loc, vec.x, vec.y, vec.z);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setUniformVec2Internal(ShaderProgram sp, String name, org.joml.Vector2f vec) {
|
||||
int loc = sp.getUniformLocation(name);
|
||||
if (loc != -1) {
|
||||
GL20.glUniform2f(loc, vec.x, vec.y);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setUniformFloatInternal(ShaderProgram sp, String name, float value) {
|
||||
int loc = sp.getUniformLocation(name);
|
||||
if (loc != -1) GL20.glUniform1f(loc, value);
|
||||
|
||||
Reference in New Issue
Block a user