1 module des.gl.simple.object; 2 3 import std.exception; 4 import std.stdio; 5 import std..string; 6 7 public import des.gl.base; 8 9 /// 10 abstract class GLSimpleObject : GLObject 11 { 12 private: 13 uint draw_count; 14 uint index_count; 15 16 GLBuffer elem_buffer = null; 17 18 protected: 19 20 /// 21 void setDrawCount( uint cnt ) { draw_count = cnt; } 22 23 /// 24 void setIndexCount( uint cnt ) { index_count = cnt; } 25 26 /// 27 CommonGLShaderProgram shader; 28 29 /// 30 bool warn_if_empty = true; 31 32 /// 33 auto createArrayBuffer() 34 { 35 auto buf = newEMM!GLBuffer( GLBuffer.Target.ARRAY_BUFFER ); 36 connect( buf.elementCountCB, &setDrawCount ); 37 return buf; 38 } 39 40 /+ ??? под вопросом +/ 41 static struct APInfo 42 { 43 string name; 44 string attrib; 45 uint per_element; 46 GLType type; 47 size_t stride = 0; 48 size_t offset = 0; 49 bool required = true; 50 51 this( string n, uint pe, GLType t, bool req=true ) 52 { 53 name = n; 54 attrib = n; 55 per_element = pe; 56 type = t; 57 required = req; 58 } 59 60 this( string n, string a, uint pe, GLType t, size_t st, size_t of, bool req=true ) 61 { 62 this( n, pe, t, req ); 63 attrib = a; 64 stride = st; 65 offset = of; 66 } 67 } 68 69 /+ ??? под вопросом +/ 70 auto createArrayBuffersFromAttributeInfo( in APInfo[] infos... ) 71 { 72 GLBuffer[string] ret; 73 foreach( info; infos ) 74 { 75 auto loc = shader.getAttribLocation( info.attrib ); 76 77 if( loc < 0 ) 78 { 79 if( info.required ) 80 assert( 0, format( "no attrib '%s' in shader", info.attrib ) ); 81 else 82 { 83 logger.warn( "no attrib '%s' in shader", info.attrib ); 84 continue; 85 } 86 } 87 88 if( info.name !in ret ) 89 ret[info.name] = createArrayBuffer(); 90 91 auto buf = ret[info.name]; 92 setAttribPointer( buf, loc, info.per_element, info.type, 93 info.stride, info.offset ); 94 } 95 return ret; 96 } 97 98 /// 99 auto createIndexBuffer() 100 { 101 auto buf = newEMM!GLBuffer( GLBuffer.Target.ELEMENT_ARRAY_BUFFER ); 102 connect( buf.elementCountCB, &setIndexCount ); 103 connect( buf.elementSizeCB, (uint sz){ 104 enforce( sz == uint.sizeof, "set to index buffer not uint data" ); 105 }); 106 elem_buffer = buf; 107 return buf; 108 } 109 110 /// 111 override void preDraw() 112 { 113 shader.use(); 114 if( elem_buffer !is null ) 115 elem_buffer.bind(); 116 debug checkGL; 117 } 118 119 /// 120 void drawArrays( DrawMode mode ) 121 { 122 if( !visible ) return; 123 if( draw_count > 0 ) 124 super.drawArrays( mode, cast(uint)draw_count ); 125 else if( warn_if_empty ) 126 logger.warn( "simple object draw empty object" ); 127 } 128 129 /// 130 void drawElements( DrawMode mode ) 131 { 132 if( !visible ) return; 133 if( index_count > 0 && draw_count > 0 ) 134 super.drawElements( mode, cast(uint)index_count ); 135 else if( warn_if_empty ) 136 logger.warn( "simple object draw empty object" ); 137 } 138 139 public: 140 141 /// 142 this( string shader_source ) 143 { 144 shader = newEMM!CommonGLShaderProgram( parseGLShaderSource( shader_source ) ); 145 } 146 147 /// 148 bool visible = true; 149 150 /// 151 this( CommonGLShaderProgram sh ) 152 in{ assert( sh !is null ); } body 153 { shader = sh; } 154 }