minecraft-src/com/mojang/blaze3d/shaders/Uniform.java
2025-07-04 02:00:41 +03:00

528 lines
13 KiB
Java

package com.mojang.blaze3d.shaders;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;
import java.util.List;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.ShaderProgramConfig;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.lwjgl.system.MemoryUtil;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class Uniform extends AbstractUniform implements AutoCloseable {
private static final Logger LOGGER = LogUtils.getLogger();
public static final int UT_INT1 = 0;
public static final int UT_INT2 = 1;
public static final int UT_INT3 = 2;
public static final int UT_INT4 = 3;
public static final int UT_FLOAT1 = 4;
public static final int UT_FLOAT2 = 5;
public static final int UT_FLOAT3 = 6;
public static final int UT_FLOAT4 = 7;
public static final int UT_MAT2 = 8;
public static final int UT_MAT3 = 9;
public static final int UT_MAT4 = 10;
private static final boolean TRANSPOSE_MATRICIES = false;
private int location;
private final int count;
private final int type;
private final IntBuffer intValues;
private final FloatBuffer floatValues;
private final String name;
public Uniform(String string, int i, int j) {
this.name = string;
this.count = j;
this.type = i;
if (i <= 3) {
this.intValues = MemoryUtil.memAllocInt(j);
this.floatValues = null;
} else {
this.intValues = null;
this.floatValues = MemoryUtil.memAllocFloat(j);
}
this.location = -1;
this.markDirty();
}
public static int glGetUniformLocation(int program, CharSequence name) {
return GlStateManager._glGetUniformLocation(program, name);
}
public static void uploadInteger(int location, int value) {
RenderSystem.glUniform1i(location, value);
}
public void setFromConfig(ShaderProgramConfig.Uniform uniform) {
this.setFromConfig(uniform.values(), uniform.count());
}
public void setFromConfig(List<Float> list, int i) {
float[] fs = new float[Math.max(i, 16)];
if (list.size() == 1) {
Arrays.fill(fs, (Float)list.getFirst());
} else {
for (int j = 0; j < list.size(); j++) {
fs[j] = (Float)list.get(j);
}
}
if (this.type <= 3) {
this.setSafe((int)fs[0], (int)fs[1], (int)fs[2], (int)fs[3]);
} else if (this.type <= 7) {
this.setSafe(fs[0], fs[1], fs[2], fs[3]);
} else {
this.set(Arrays.copyOfRange(fs, 0, i));
}
}
public void close() {
if (this.intValues != null) {
MemoryUtil.memFree(this.intValues);
}
if (this.floatValues != null) {
MemoryUtil.memFree(this.floatValues);
}
}
private void markDirty() {
}
public static int getTypeFromString(String typeName) {
int i = -1;
if ("int".equals(typeName)) {
i = 0;
} else if ("float".equals(typeName)) {
i = 4;
} else if (typeName.startsWith("matrix")) {
if (typeName.endsWith("2x2")) {
i = 8;
} else if (typeName.endsWith("3x3")) {
i = 9;
} else if (typeName.endsWith("4x4")) {
i = 10;
}
}
return i;
}
public void setLocation(int location) {
this.location = location;
}
public String getName() {
return this.name;
}
@Override
public final void set(float x) {
this.floatValues.position(0);
this.floatValues.put(0, x);
this.markDirty();
}
@Override
public final void set(float x, float y) {
this.floatValues.position(0);
this.floatValues.put(0, x);
this.floatValues.put(1, y);
this.markDirty();
}
public final void set(int index, float value) {
this.floatValues.position(0);
this.floatValues.put(index, value);
this.markDirty();
}
@Override
public final void set(float x, float y, float z) {
this.floatValues.position(0);
this.floatValues.put(0, x);
this.floatValues.put(1, y);
this.floatValues.put(2, z);
this.markDirty();
}
@Override
public final void set(Vector3f vector) {
this.floatValues.position(0);
vector.get(this.floatValues);
this.markDirty();
}
@Override
public final void set(float x, float y, float z, float w) {
this.floatValues.position(0);
this.floatValues.put(x);
this.floatValues.put(y);
this.floatValues.put(z);
this.floatValues.put(w);
this.floatValues.flip();
this.markDirty();
}
@Override
public final void set(Vector4f vector) {
this.floatValues.position(0);
vector.get(this.floatValues);
this.markDirty();
}
@Override
public final void setSafe(float x, float y, float z, float w) {
this.floatValues.position(0);
if (this.type >= 4) {
this.floatValues.put(0, x);
}
if (this.type >= 5) {
this.floatValues.put(1, y);
}
if (this.type >= 6) {
this.floatValues.put(2, z);
}
if (this.type >= 7) {
this.floatValues.put(3, w);
}
this.markDirty();
}
@Override
public final void setSafe(int x, int y, int z, int w) {
this.intValues.position(0);
if (this.type >= 0) {
this.intValues.put(0, x);
}
if (this.type >= 1) {
this.intValues.put(1, y);
}
if (this.type >= 2) {
this.intValues.put(2, z);
}
if (this.type >= 3) {
this.intValues.put(3, w);
}
this.markDirty();
}
@Override
public final void set(int x) {
this.intValues.position(0);
this.intValues.put(0, x);
this.markDirty();
}
@Override
public final void set(int x, int y) {
this.intValues.position(0);
this.intValues.put(0, x);
this.intValues.put(1, y);
this.markDirty();
}
@Override
public final void set(int x, int y, int z) {
this.intValues.position(0);
this.intValues.put(0, x);
this.intValues.put(1, y);
this.intValues.put(2, z);
this.markDirty();
}
@Override
public final void set(int x, int y, int z, int w) {
this.intValues.position(0);
this.intValues.put(0, x);
this.intValues.put(1, y);
this.intValues.put(2, z);
this.intValues.put(3, w);
this.markDirty();
}
@Override
public final void set(float[] valueArray) {
if (valueArray.length < this.count) {
LOGGER.warn("Uniform.set called with a too-small value array (expected {}, got {}). Ignoring.", this.count, valueArray.length);
} else {
this.floatValues.position(0);
this.floatValues.put(valueArray);
this.floatValues.position(0);
this.markDirty();
}
}
@Override
public final void setMat2x2(float m00, float m01, float m10, float m11) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m10);
this.floatValues.put(3, m11);
this.markDirty();
}
@Override
public final void setMat2x3(float m00, float m01, float m02, float m10, float m11, float m12) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m02);
this.floatValues.put(3, m10);
this.floatValues.put(4, m11);
this.floatValues.put(5, m12);
this.markDirty();
}
@Override
public final void setMat2x4(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m02);
this.floatValues.put(3, m03);
this.floatValues.put(4, m10);
this.floatValues.put(5, m11);
this.floatValues.put(6, m12);
this.floatValues.put(7, m13);
this.markDirty();
}
@Override
public final void setMat3x2(float m00, float m01, float m10, float m11, float m20, float m21) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m10);
this.floatValues.put(3, m11);
this.floatValues.put(4, m20);
this.floatValues.put(5, m21);
this.markDirty();
}
@Override
public final void setMat3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m02);
this.floatValues.put(3, m10);
this.floatValues.put(4, m11);
this.floatValues.put(5, m12);
this.floatValues.put(6, m20);
this.floatValues.put(7, m21);
this.floatValues.put(8, m22);
this.markDirty();
}
@Override
public final void setMat3x4(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m02);
this.floatValues.put(3, m03);
this.floatValues.put(4, m10);
this.floatValues.put(5, m11);
this.floatValues.put(6, m12);
this.floatValues.put(7, m13);
this.floatValues.put(8, m20);
this.floatValues.put(9, m21);
this.floatValues.put(10, m22);
this.floatValues.put(11, m23);
this.markDirty();
}
@Override
public final void setMat4x2(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m02);
this.floatValues.put(3, m03);
this.floatValues.put(4, m10);
this.floatValues.put(5, m11);
this.floatValues.put(6, m12);
this.floatValues.put(7, m13);
this.markDirty();
}
@Override
public final void setMat4x3(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20, float m21, float m22, float m23) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m02);
this.floatValues.put(3, m03);
this.floatValues.put(4, m10);
this.floatValues.put(5, m11);
this.floatValues.put(6, m12);
this.floatValues.put(7, m13);
this.floatValues.put(8, m20);
this.floatValues.put(9, m21);
this.floatValues.put(10, m22);
this.floatValues.put(11, m23);
this.markDirty();
}
@Override
public final void setMat4x4(
float m00,
float m01,
float m02,
float m03,
float m10,
float m11,
float m12,
float m13,
float m20,
float m21,
float m22,
float m23,
float m30,
float m31,
float m32,
float m33
) {
this.floatValues.position(0);
this.floatValues.put(0, m00);
this.floatValues.put(1, m01);
this.floatValues.put(2, m02);
this.floatValues.put(3, m03);
this.floatValues.put(4, m10);
this.floatValues.put(5, m11);
this.floatValues.put(6, m12);
this.floatValues.put(7, m13);
this.floatValues.put(8, m20);
this.floatValues.put(9, m21);
this.floatValues.put(10, m22);
this.floatValues.put(11, m23);
this.floatValues.put(12, m30);
this.floatValues.put(13, m31);
this.floatValues.put(14, m32);
this.floatValues.put(15, m33);
this.markDirty();
}
@Override
public final void set(Matrix4f matrix) {
this.floatValues.position(0);
matrix.get(this.floatValues);
this.markDirty();
}
@Override
public final void set(Matrix3f matrix) {
this.floatValues.position(0);
matrix.get(this.floatValues);
this.markDirty();
}
public void upload() {
if (this.type <= 3) {
this.uploadAsInteger();
} else if (this.type <= 7) {
this.uploadAsFloat();
} else {
if (this.type > 10) {
LOGGER.warn("Uniform.upload called, but type value ({}) is not a valid type. Ignoring.", this.type);
return;
}
this.uploadAsMatrix();
}
}
private void uploadAsInteger() {
this.intValues.rewind();
switch (this.type) {
case 0:
RenderSystem.glUniform1(this.location, this.intValues);
break;
case 1:
RenderSystem.glUniform2(this.location, this.intValues);
break;
case 2:
RenderSystem.glUniform3(this.location, this.intValues);
break;
case 3:
RenderSystem.glUniform4(this.location, this.intValues);
break;
default:
LOGGER.warn("Uniform.upload called, but count value ({}) is not in the range of 1 to 4. Ignoring.", this.count);
}
}
private void uploadAsFloat() {
this.floatValues.rewind();
switch (this.type) {
case 4:
RenderSystem.glUniform1(this.location, this.floatValues);
break;
case 5:
RenderSystem.glUniform2(this.location, this.floatValues);
break;
case 6:
RenderSystem.glUniform3(this.location, this.floatValues);
break;
case 7:
RenderSystem.glUniform4(this.location, this.floatValues);
break;
default:
LOGGER.warn("Uniform.upload called, but count value ({}) is not in the range of 1 to 4. Ignoring.", this.count);
}
}
private void uploadAsMatrix() {
this.floatValues.clear();
switch (this.type) {
case 8:
RenderSystem.glUniformMatrix2(this.location, false, this.floatValues);
break;
case 9:
RenderSystem.glUniformMatrix3(this.location, false, this.floatValues);
break;
case 10:
RenderSystem.glUniformMatrix4(this.location, false, this.floatValues);
}
}
public int getLocation() {
return this.location;
}
public int getCount() {
return this.count;
}
public int getType() {
return this.type;
}
public IntBuffer getIntBuffer() {
return this.intValues;
}
public FloatBuffer getFloatBuffer() {
return this.floatValues;
}
}