@@ -163,6 +163,13 @@ use OpenGL::Modern qw(
163163 glGenBuffers_p glBindBuffer glDeleteBuffers_p glBufferData_c
164164 glGenTextures_p glBindTexture glDeleteTextures_p
165165 glTexImage2D_c glTexParameteri
166+ glCreateShader glDeleteShader glShaderSource_p glCompileShader
167+ glAttachShader glDetachShader
168+ glGetShaderiv_p glGetShaderInfoLog_p
169+ glCreateProgram glDeleteProgram glLinkProgram glUseProgram
170+ glGetProgramiv_p glGetProgramInfoLog_p
171+ GL_COMPILE_STATUS GL_LINK_STATUS GL_FALSE
172+ GL_VERTEX_SHADER GL_FRAGMENT_SHADER GL_CURRENT_PROGRAM
166173 GL_VERTEX_ARRAY GL_COLOR_ARRAY GL_TEXTURE_COORD_ARRAY GL_NORMAL_ARRAY
167174 GL_LIGHTING_BIT GL_ENABLE_BIT GL_DEPTH_TEST GL_LIGHTING GL_LIGHT0
168175 GL_LIGHT_MODEL_TWO_SIDE GL_TRUE GL_POSITION
@@ -232,6 +239,9 @@ sub togl_bind {
232239 if (defined $this -> {Impl }{indx_buf }) {
233240 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, $this -> {Impl }{indx_buf }); # unbind the VAO before you unbind the Index Buffer
234241 }
242+ if (my ($program_key ) = grep /^program/, keys %{ $this -> {Impl } }) {
243+ glUseProgram($this -> {Impl }{$program_key });
244+ }
235245}
236246sub togl_unbind {
237247 my ($this ) = @_ ;
@@ -244,6 +254,48 @@ sub togl_unbind {
244254 glBindTexture(GL_TEXTURE_2D, 0);
245255 glDisable(GL_TEXTURE_2D);
246256 }
257+ glUseProgram(0) if grep /^program/, keys %{ $this -> {Impl } };
258+ }
259+ sub compile_shader {
260+ my ($this , $type , $src ) = @_ ;
261+ my $shader = glCreateShader($type );
262+ glShaderSource_p($shader , $src );
263+ glCompileShader($shader );
264+ my $status = glGetShaderiv_p($shader , GL_COMPILE_STATUS);
265+ if ($status == GL_FALSE) {
266+ my $str = sprintf (" %s shader compilation failed!\n " ,
267+ $type == GL_VERTEX_SHADER ? " Vertex" : " Fragment" );
268+ $str .= glGetShaderInfoLog_p($shader );
269+ glDeleteShader($shader );
270+ die $str ;
271+ }
272+ $shader ;
273+ }
274+ sub compile_program {
275+ my ($this , $vsrc , $fsrc , $prelink ) = @_ ;
276+ my $vShader = $this -> compile_shader(GL_VERTEX_SHADER, $vsrc );
277+ my $fShader = $fsrc && eval { $this -> compile_shader(GL_FRAGMENT_SHADER, $fsrc ) };
278+ if (my $err = $@ ) {
279+ glDeleteShader($vShader );
280+ die $err ;
281+ }
282+ my $program = glCreateProgram();
283+ glAttachShader($program , $vShader );
284+ glAttachShader($program , $fShader ) if $fsrc ;
285+ $prelink -> ($program ) if $prelink ;
286+ glLinkProgram($program );
287+ my $status = glGetProgramiv_p($program , GL_LINK_STATUS);
288+ glDetachShader($program , $vShader );
289+ glDetachShader($program , $fShader ) if $fsrc ;
290+ glDeleteShader($vShader );
291+ glDeleteShader($fShader ) if $fsrc ;
292+ if ($status == GL_FALSE) {
293+ my $str = " Program linker failed.\n " ;
294+ $str .= glGetProgramInfoLog_p($program );
295+ glDeleteProgram($program );
296+ die $str ;
297+ }
298+ $program ;
247299}
248300sub togl {
249301 my ($this , $points ) = @_ ;
@@ -284,6 +336,10 @@ sub DESTROY {
284336 glBindTexture(GL_TEXTURE_2D, 0) if glGetIntegerv_p(GL_TEXTURE_BINDING_2D) == $tex_id ;
285337 glDeleteTextures_p($tex_id );
286338 }
339+ if (my $program = $this -> {Impl }{program }) {
340+ glUseProgram(0) if glGetIntegerv_p(GL_CURRENT_PROGRAM) == $program ;
341+ glDeleteProgram($_ ) for grep $_ , $program ;
342+ }
287343}
288344}
289345
0 commit comments