Last active
August 16, 2016 16:22
-
-
Save riccardobl/176601e1047a54d4d9eed6524532da42 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW; | |
import static org.lwjgl.opengl.GL15.glBindBuffer; | |
import static org.lwjgl.opengl.GL15.glBufferData; | |
import static org.lwjgl.opengl.GL15.glDeleteBuffers; | |
import static org.lwjgl.opengl.GL15.glGenBuffers; | |
import static org.lwjgl.opengl.GL30.glBindBufferBase; | |
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER; | |
import java.io.IOException; | |
import java.lang.reflect.Field; | |
import java.nio.ByteBuffer; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.Map; | |
import com.jme3.math.Vector2f; | |
import com.jme3.math.Vector3f; | |
import com.jme3.math.Vector4f; | |
import com.jme3.util.BufferUtils; | |
import lombok.extern.log4j.Log4j2; | |
@Log4j2 | |
public class BindUniformBlocksSTD140{ | |
// https://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt | |
private static class Pointer <T>{ | |
public T ref; | |
public Pointer(T t){ | |
ref=t; | |
} | |
@Override | |
public String toString(){ | |
return "P!["+ref.toString()+"]"; | |
} | |
} | |
private static final Map<Object,Integer> _ALLOCATIONS=new HashMap<Object,Integer>(); | |
public static void bind(int binding_point,Object o){ | |
try{ | |
// Collect data | |
ArrayList<Object> data=collectData(o); | |
// Write in tmp bytebuffer | |
Pointer<Integer> witten_bytesp=new Pointer<Integer>(0); | |
Pointer<ByteBuffer> bbf_p=new Pointer<ByteBuffer>(BufferUtils.createByteBuffer(1)); | |
for(Object d:data)toByteBuffer(bbf_p,witten_bytesp,d); | |
ByteBuffer bbf=bbf_p.ref; | |
bbf.limit(bbf.position()); | |
bbf.rewind(); | |
LOGGER.debug("Allocated {}[=={}] bytes", bbf.limit(),witten_bytesp); | |
if(LOGGER.isDebugEnabled()){ | |
byte[] bytes=new byte[bbf.limit()]; | |
bbf.get(bytes); | |
LOGGER.debug("Bytes: {}",bytes); | |
bbf.rewind(); | |
} | |
// Build GPU buffer | |
int bid=glGenBuffers(); | |
LOGGER.debug("Buffer id {}",bid); | |
// Bind | |
glBindBufferBase(GL_UNIFORM_BUFFER, binding_point, bid); | |
// Set data | |
glBindBuffer(GL_UNIFORM_BUFFER,bid); | |
glBufferData(GL_UNIFORM_BUFFER,bbf,GL_STATIC_DRAW); | |
glBindBuffer(GL_UNIFORM_BUFFER,0); | |
// Store references for destruction | |
_ALLOCATIONS.put(o,bid); | |
// Clean tmp data | |
BufferUtils.destroyDirectBuffer(bbf); | |
}catch(Exception e){ | |
e.printStackTrace(); | |
} | |
} | |
public static void unbind(Object o){ | |
Integer bid=_ALLOCATIONS.remove(o); | |
glDeleteBuffers(bid); | |
} | |
// Helpers | |
private static ArrayList<Object> collectData(Object f) throws IOException, IllegalArgumentException, IllegalAccessException{ | |
Field fields[]=f.getClass().getDeclaredFields(); | |
ArrayList<Object> ordered_fields=new ArrayList<Object>(); | |
for(Field field:fields){ | |
FieldOrder glslfield=field.getAnnotation(FieldOrder.class); | |
if(glslfield==null)continue; | |
int id=glslfield.position(); | |
while(ordered_fields.size()<=id)ordered_fields.add(null); | |
ordered_fields.set(id,(field.get(f))); | |
} | |
return ordered_fields; | |
} | |
private static void toByteBuffer(Pointer<ByteBuffer> bbf_p,Pointer<Integer> witten_bytesp,Object o) throws IllegalArgumentException, IllegalAccessException, IOException{ | |
int bytesn_before=bbf_p.ref.position(); | |
if(o instanceof Float){ | |
Float f=(Float)o; | |
extendsByteBuffer(bbf_p,4,4); | |
bbf_p.ref.putFloat(f); | |
}else if(o instanceof Integer||o instanceof Boolean){ | |
Integer f=o instanceof Integer?(Integer)o:((Boolean)o)?1:0; | |
extendsByteBuffer(bbf_p,4,4); | |
bbf_p.ref.putInt(f); | |
}else if(o instanceof Vector2f){ | |
Vector2f f=(Vector2f)o; | |
extendsByteBuffer(bbf_p,8,8); | |
bbf_p.ref.putFloat(f.x); | |
bbf_p.ref.putFloat(f.y); | |
}else if(o instanceof Vector3f){ | |
extendsByteBuffer(bbf_p,16,16); | |
Vector3f v3=(Vector3f)o; | |
bbf_p.ref.putFloat(v3.x); | |
bbf_p.ref.putFloat(v3.y); | |
bbf_p.ref.putFloat(v3.z); | |
}else if(o instanceof Vector4f){ | |
extendsByteBuffer(bbf_p,16,16); | |
Vector4f f=(Vector4f)o; | |
bbf_p.ref.putFloat(f.x); | |
bbf_p.ref.putFloat(f.y); | |
bbf_p.ref.putFloat(f.z); | |
bbf_p.ref.putFloat(f.w); | |
}else if(o instanceof Struct){ | |
extendsByteBuffer(bbf_p,16,16); // ?????? | |
ArrayList<Object> data=collectData(o); | |
for(Object o2:data){ | |
Pointer<Integer> wb2=new Pointer<Integer>(0); | |
toByteBuffer(bbf_p,wb2,o2); | |
} | |
extendsByteBuffer(bbf_p,16,16); | |
}else if(o.getClass().isArray()){ | |
Object aro[]=(Object[])o; | |
if(!(aro instanceof Struct[]))extendsByteBuffer(bbf_p,16,16); // ?????????? | |
for(Object ao:aro){ | |
if(ao instanceof Float){ | |
bbf_p.ref.putFloat((Float)ao); | |
bbf_p.ref.putFloat(0); | |
bbf_p.ref.putFloat(0); | |
bbf_p.ref.putFloat(0); | |
}else if(ao instanceof Integer||ao instanceof Boolean[]){ | |
Integer f=ao instanceof Integer?(Integer)ao:((Boolean)ao)?1:0; | |
bbf_p.ref.putInt(f); | |
bbf_p.ref.putInt(0); | |
bbf_p.ref.putInt(0); | |
bbf_p.ref.putInt(0); | |
}else if(ao instanceof Vector2f){ | |
Vector2f f=(Vector2f)ao; | |
bbf_p.ref.putFloat(f.x); | |
bbf_p.ref.putFloat(f.y); | |
bbf_p.ref.putFloat(0); | |
bbf_p.ref.putFloat(0); | |
}else if(ao instanceof Vector3f){ | |
Vector3f f=(Vector3f)ao; | |
bbf_p.ref.putFloat(f.x); | |
bbf_p.ref.putFloat(f.y); | |
bbf_p.ref.putFloat(f.z); | |
bbf_p.ref.putFloat(0); | |
}else if(ao instanceof Vector4f){ | |
Vector4f f=(Vector4f)ao; | |
bbf_p.ref.putFloat(f.x); | |
bbf_p.ref.putFloat(f.y); | |
bbf_p.ref.putFloat(f.z); | |
bbf_p.ref.putFloat(f.w); | |
}else if(ao instanceof Struct){ | |
Pointer<Integer> wb2=new Pointer<Integer>(0); | |
toByteBuffer(bbf_p,wb2,ao); | |
} | |
} | |
} | |
int bytesn_after=bbf_p.ref.position(); | |
int delta_bytesn=bytesn_after-bytesn_before; | |
witten_bytesp.ref=delta_bytesn; | |
} | |
private static void extendsByteBuffer(Pointer<ByteBuffer> bbf_p,int base_alignment,int desired_size){ | |
ByteBuffer bbf=bbf_p.ref; | |
int pos=bbf.position(); | |
int required_pos=toMultipleOf(pos,base_alignment); | |
pos=required_pos; | |
int extend=bbf.limit()-(required_pos+desired_size); | |
if(extend<=0){ | |
ByteBuffer newb=BufferUtils.createByteBuffer(bbf.limit()+Math.max(extend,1024)); | |
bbf.flip(); | |
newb.put(bbf); | |
newb.position(pos); | |
BufferUtils.destroyDirectBuffer(bbf); | |
bbf_p.ref=newb; | |
}else{ | |
bbf.position(pos); | |
} | |
} | |
private static int toMultipleOf(int n,int of){ | |
return ((n-1)|(of-1))+1; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#extension GL_ARB_shading_language_420pack : enable | |
struct MyStruct{ | |
float a; | |
vec3 b; | |
float v; | |
}; | |
layout(std140, binding = 11) uniform MyBlock{ | |
MyStruct s_myStruct[2]; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Block{ | |
public static class MyStruct implements Struct{ | |
@FieldOrder(position=1) | |
public Vector3f a; | |
@FieldOrder(position=0) | |
public float b; | |
@FieldOrder(position=2) | |
public float c; | |
} | |
@FieldOrder(position=0) | |
public MyStruct s_myStruct[]=new MyStruct[2]; | |
} | |
BindUniformBlocksSTD140.bind(11,new Block(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.annotation.ElementType; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.lang.annotation.Target; | |
@Retention(RetentionPolicy.RUNTIME) | |
@Target(ElementType.FIELD) | |
public @interface FieldOrder { | |
public int position(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Struct{ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment