Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enables images to be read and modified per pixel in shader #2331

Merged
merged 11 commits into from
Jan 8, 2025
15 changes: 12 additions & 3 deletions jme3-core/src/main/java/com/jme3/material/Material.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import com.jme3.shader.bufferobject.BufferObject;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.TextureImage;
import com.jme3.texture.image.ColorSpace;
import com.jme3.util.ListMap;
import com.jme3.util.SafeArrayList;
Expand Down Expand Up @@ -451,7 +452,7 @@ public MatParamTexture getTextureParam(String name) {
}
return null;
}

/**
* Returns a collection of all parameters set on this material.
*
Expand Down Expand Up @@ -514,6 +515,10 @@ public void setParam(String name, VarType type, Object value) {
if (technique != null) {
technique.notifyParamChanged(name, type, value);
}
if (type.isImageType()) {
// recompute sort id
sortingId = -1;
}
}
}

Expand Down Expand Up @@ -859,9 +864,13 @@ private void updateShaderMaterialParameter(Renderer renderer, VarType type, Shad
Uniform uniform = shader.getUniform(param.getPrefixedName());
if (!override && uniform.isSetByCurrentMaterial()) return;

if (type.isTextureType()) {
if (type.isTextureType() || type.isImageType()) {
try {
renderer.setTexture(unit.textureUnit, (Texture) param.getValue());
if (type.isTextureType()) {
renderer.setTexture(unit.textureUnit, (Texture) param.getValue());
} else {
renderer.setTextureImage(unit.textureUnit, (TextureImage) param.getValue());
}
} catch (TextureUnitException exception) {
int numTexParams = unit.textureUnit + 1;
String message = "Too many texture parameters (" + numTexParams + ") assigned\n to " + toString();
Expand Down
10 changes: 10 additions & 0 deletions jme3-core/src/main/java/com/jme3/renderer/Renderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.TextureImage;
import com.jme3.util.NativeObject;
import java.nio.ByteBuffer;
import java.util.EnumMap;
Expand Down Expand Up @@ -273,6 +274,15 @@ public interface Renderer {
*/
public void setTexture(int unit, Texture tex)
throws TextureUnitException;

/**
* Assigns a TextureImage to the specified texture unit.
*
* @param unit the index of the texture unit (≥0)
* @param tex the texture image to assign
* @throws TextureUnitException if the texture unit does not exist
*/
public void setTextureImage(int unit, TextureImage tex) throws TextureUnitException;

/**
* Modifies the given Texture with the given Image.
Expand Down
4 changes: 4 additions & 0 deletions jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ public interface GL2 extends GL {
public static final int GL_TEXTURE_WRAP_R = 0x8072;
public static final int GL_VERTEX_PROGRAM_POINT_SIZE = 0x8642;
public static final int GL_UNSIGNED_INT_8_8_8_8 = 0x8035;

public static final int GL_READ_ONLY = 35000;
public static final int GL_WRITE_ONLY = 35001;
public static final int GL_READ_WRITE = 35002;

/**
* <p><a target="_blank" href="http://docs.gl/gl3/glAlphaFunc">Reference Page</a> - <em>This function is deprecated and unavailable in the Core profile</em></p>
Expand Down
15 changes: 15 additions & 0 deletions jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,19 @@ public interface GL4 extends GL3 {
* @param storageBlockBinding The index storage block binding to associate with the specified storage block.
*/
public void glShaderStorageBlockBinding(int program, int storageBlockIndex, int storageBlockBinding);

/**
* Binds a single level of a texture to an image unit for the purpose of reading
* and writing it from shaders.
*
* @param unit image unit to bind to
* @param texture texture to bind to the image unit
* @param level level of the texture to bind
* @param layered true to bind all array elements
* @param layer if not layered, the layer to bind
* @param access access types that may be performed
* @param format format to use when performing formatted stores
*/
public void glBindImageTexture(int unit, int texture, int level, boolean layered, int layer, int access, int format);

}
16 changes: 15 additions & 1 deletion jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import com.jme3.texture.Texture2D;
import com.jme3.texture.Texture.ShadowCompareMode;
import com.jme3.texture.Texture.WrapAxis;
import com.jme3.texture.TextureImage;
import com.jme3.texture.image.LastTextureState;
import com.jme3.util.BufferUtils;
import com.jme3.util.ListMap;
Expand Down Expand Up @@ -2752,7 +2753,20 @@ public void setTexture(int unit, Texture tex) throws TextureUnitException {
if (tex.getName() != null) glext.glObjectLabel(GL.GL_TEXTURE, tex.getImage().getId(), tex.getName());
}
}


@Override
public void setTextureImage(int unit, TextureImage tex) throws TextureUnitException {
if (unit < 0 || unit >= RenderContext.maxTextureUnits) {
throw new TextureUnitException();
}
WeakReference<Image> ref = context.boundTextures[unit];
boolean bindRequired = tex.clearUpdateNeeded() || ref == null || ref.get() != tex.getImage().getWeakRef().get();
setTexture(unit, tex.getTexture());
if (gl4 != null && bindRequired) {
tex.bindImage(gl4, texUtil, unit);
}
}

@Override
public void setUniformBufferObject(int bindingPoint, BufferObject bufferObject) {
if (bufferObject.isUpdateNeeded()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2021 jMonkeyEngine
* Copyright (c) 2009-2024 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -46,7 +46,7 @@
*
* @author Kirill Vainer
*/
final class TextureUtil {
public final class TextureUtil {

private static final Logger logger = Logger.getLogger(TextureUtil.class.getName());

Expand Down
21 changes: 18 additions & 3 deletions jme3-core/src/main/java/com/jme3/shader/VarType.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@
import com.jme3.texture.Texture3D;
import com.jme3.texture.TextureArray;
import com.jme3.texture.TextureCubeMap;
import com.jme3.texture.TextureImage;

public enum VarType {

Float("float", float.class, Float.class),
Vector2("vec2", Vector2f.class),
Vector3("vec3", Vector3f.class),
Expand All @@ -56,7 +57,8 @@ public enum VarType {
Vector2Array(true, false, "vec2", Vector2f[].class),
Vector3Array(true, false, "vec3", Vector3f[].class),
Vector4Array(true, false, "vec4", Vector4f[].class),


Int("int", int.class, Integer.class),
Boolean("bool", Boolean.class, boolean.class),

Matrix3(true, false, "mat3", Matrix3f.class),
Expand All @@ -70,12 +72,16 @@ public enum VarType {
Texture3D(false, true, "sampler3D", Texture3D.class, Texture.class),
TextureArray(false, true, "sampler2DArray|sampler2DArrayShadow", TextureArray.class, Texture.class),
TextureCubeMap(false, true, "samplerCube", TextureCubeMap.class, Texture.class),
Int("int", int.class, Integer.class),

Image2D(false, false, true, "image2D", TextureImage.class),
Image3D(false, false, true, "image3D", TextureImage.class),

UniformBufferObject(false, false, "custom", BufferObject.class),
ShaderStorageBufferObject(false, false, "custom", BufferObject.class);

private boolean usesMultiData = false;
private boolean textureType = false;
private boolean imageType = false;
private final String glslType;
private Class<?>[] javaTypes;

Expand All @@ -98,6 +104,11 @@ public enum VarType {
this.javaTypes = new Class<?>[0];
}
}

VarType(boolean multiData, boolean textureType, boolean imageType, String glslType, Class<?>... javaTypes) {
this(multiData, textureType, glslType, javaTypes);
this.imageType = imageType;
}

/**
* Check if the passed object is of a type mapped to this VarType
Expand Down Expand Up @@ -126,6 +137,10 @@ public Class<?>[] getJavaType() {
public boolean isTextureType() {
return textureType;
}

public boolean isImageType() {
return imageType;
}

public boolean usesMultiData() {
return usesMultiData;
Expand Down
7 changes: 7 additions & 0 deletions jme3-core/src/main/java/com/jme3/system/NullRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture;
import com.jme3.texture.TextureImage;

import java.nio.ByteBuffer;
import java.util.EnumMap;
Expand Down Expand Up @@ -170,6 +171,11 @@ public void deleteFrameBuffer(FrameBuffer fb) {
public void setTexture(int unit, Texture tex) throws TextureUnitException {
// do nothing
}

@Override
public void setTextureImage(int unit, TextureImage tex) throws TextureUnitException {
// do nothing
}

@Override
public void modifyTexture(Texture tex, Image pixels, int x, int y) {
Expand Down Expand Up @@ -314,4 +320,5 @@ public void setShaderStorageBufferObject(int bindingPoint, BufferObject bufferOb
public void setUniformBufferObject(int bindingPoint, BufferObject bufferObject) {

}

}
1 change: 0 additions & 1 deletion jme3-core/src/main/java/com/jme3/texture/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -1299,7 +1299,6 @@ public void read(JmeImporter importer) throws IOException {
multiSamples = capsule.readInt("multiSamples", 1);
data = capsule.readByteBufferArrayList("data", null);
colorSpace = capsule.readEnum("colorSpace", ColorSpace.class, null);

if (mipMapSizes != null) {
needGeneratedMips = false;
mipsWereGenerated = true;
Expand Down
Loading
Loading