Skip to content

Commit

Permalink
Merge pull request #2331 from codex128/imageShaderMod
Browse files Browse the repository at this point in the history
Enables images to be read and modified per pixel in shader
  • Loading branch information
yaRnMcDonuts authored Jan 8, 2025
2 parents 6e125d9 + d8b63d5 commit 662b4ea
Show file tree
Hide file tree
Showing 15 changed files with 510 additions and 12 deletions.
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

0 comments on commit 662b4ea

Please sign in to comment.