Skip to content

Instantly share code, notes, and snippets.

@riccardobl
Last active August 16, 2016 16:22
Show Gist options
  • Save riccardobl/176601e1047a54d4d9eed6524532da42 to your computer and use it in GitHub Desktop.
Save riccardobl/176601e1047a54d4d9eed6524532da42 to your computer and use it in GitHub Desktop.
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;
}
}
#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];
};
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();
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();
}
public interface Struct{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment