/* * demoscene-eo, an ASCII art demoscene written as a gift for Emmanuel Otton retirement * Copyright (C) 2019 XXXXXX XXXXXXX * * This file is part of demoscene-eo. * * demoscene-eo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * demoscene-eo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with demoscene-eo. If not, see */ #include "scene01.h" // Mostly inspired by CC0 https://gist.github.com/koute/7391344 typedef float t_mat4x4[16]; static inline void mat4x4_ortho( t_mat4x4 out, float left, float right, float bottom, float top, float znear, float zfar ) { #define T(a, b) (a * 4 + b) out[T(0,0)] = 2.0f / (right - left); out[T(0,1)] = 0.0f; out[T(0,2)] = 0.0f; out[T(0,3)] = 0.0f; out[T(1,1)] = 2.0f / (top - bottom); out[T(1,0)] = 0.0f; out[T(1,2)] = 0.0f; out[T(1,3)] = 0.0f; out[T(2,2)] = -2.0f / (zfar - znear); out[T(2,0)] = 0.0f; out[T(2,1)] = 0.0f; out[T(2,3)] = 0.0f; out[T(3,0)] = -(right + left) / (right - left); out[T(3,1)] = -(top + bottom) / (top - bottom); out[T(3,2)] = -(zfar + znear) / (zfar - znear); out[T(3,3)] = 1.0f; #undef T } static const char * vertex_shader = "#version 130\n" "in vec2 i_position;\n" "in vec4 i_color;\n" "out vec4 v_color;\n" "uniform mat4 u_projection_matrix;\n" "void main() {\n" " v_color = i_color;\n" " gl_Position = u_projection_matrix * vec4( i_position, 0.0, 1.0 );\n" "}\n"; static const char * fragment_shader = "#version 130\n" "in vec4 v_color;\n" "out vec4 o_color;\n" "void main() {\n" " o_color = v_color;\n" "}\n"; typedef enum t_attrib_id { attrib_position, attrib_color } t_attrib_id; int scene01_init_gl(graphical_env_t *ge, scene01_env_t *se) { GLuint vs, fs, program; vs = glCreateShader( GL_VERTEX_SHADER ); fs = glCreateShader( GL_FRAGMENT_SHADER ); int length = strlen( vertex_shader ); glShaderSource( vs, 1, ( const GLchar ** )&vertex_shader, &length ); glCompileShader( vs ); GLint status; glGetShaderiv( vs, GL_COMPILE_STATUS, &status ); if( status == GL_FALSE ) { fprintf( stderr, "vertex shader compilation failed\n" ); return 1; } length = strlen( fragment_shader ); glShaderSource( fs, 1, ( const GLchar ** )&fragment_shader, &length ); glCompileShader( fs ); glGetShaderiv( fs, GL_COMPILE_STATUS, &status ); if( status == GL_FALSE ) { fprintf( stderr, "fragment shader compilation failed\n" ); return 1; } program = glCreateProgram(); glAttachShader( program, vs ); glAttachShader( program, fs ); glBindAttribLocation( program, attrib_position, "i_position" ); glBindAttribLocation( program, attrib_color, "i_color" ); glLinkProgram( program ); glUseProgram( program ); glDisable( GL_DEPTH_TEST ); //glClearColor( 0.5, 0.0, 0.0, 0.0 ); glClearColor( 0.5, 0.5, 0.0, 0.0 ); glViewport( 0, 0, FBUF_W, FBUF_H ); GLuint vbo; glGenVertexArrays( 1, &(se->vao) ); glGenBuffers( 1, &vbo ); glBindVertexArray( se->vao ); glBindBuffer( GL_ARRAY_BUFFER, vbo ); glEnableVertexAttribArray( attrib_position ); glEnableVertexAttribArray( attrib_color ); glVertexAttribPointer( attrib_color, 4, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, 0 ); glVertexAttribPointer( attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof( float ) * 6, ( void * )(4 * sizeof(float)) ); const GLfloat g_vertex_buffer_data[] = { /* R, G, B, A, X, Y */ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, FBUF_W, 0, 0, 0, 1, 1, FBUF_W, FBUF_H, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, FBUF_W, FBUF_H, 1, 1, 1, 1, 0, FBUF_H }; glBufferData( GL_ARRAY_BUFFER, sizeof( g_vertex_buffer_data ), g_vertex_buffer_data, GL_STATIC_DRAW ); t_mat4x4 projection_matrix; mat4x4_ortho( projection_matrix, 0.0f, (float)FBUF_W, (float)FBUF_H, 0.0f, 0.0f, 100.0f ); glUniformMatrix4fv( glGetUniformLocation( program, "u_projection_matrix" ), 1, GL_FALSE, projection_matrix ); return 0; } int scene01_init_sdl(graphical_env_t *ge, scene01_env_t *se) { return 0; } int scene01_init_caca(graphical_env_t *ge, scene01_env_t *se) { return 0; } void scene01_free_gl(graphical_env_t *ge, scene01_env_t *se) { //TODO } void scene01_free_sdl(graphical_env_t *ge, scene01_env_t *se) { } void scene01_free_caca(graphical_env_t *ge, scene01_env_t *se) { } int scene01_next_gl(graphical_env_t *ge, scene01_env_t *se) { // Shorthands caca_canvas_t *cv = ge->cv; int w = ge->w, h = ge->h; SDL_Renderer *r = ge->sdl_rndr; // Local vars int res; // https://gist.github.com/Twinklebear/8265888 // https://forums.libsdl.org/viewtopic.php?p=51634 // Render all the stuff on target texture SDL_SetRenderTarget(r, ge->sdl_target); glClear( GL_COLOR_BUFFER_BIT ); glBindVertexArray( se->vao ); glDrawArrays( GL_TRIANGLES, 0, 6 ); // Copy the SDL screen to SDL debug window (and display it, not mandatory) SDL_SetRenderTarget(r, NULL); SDL_RenderCopy(r, ge->sdl_target, NULL, NULL); SDL_RenderPresent(r); // Download the rendered texture from videocard to main memory SDL_SetRenderTarget(r, ge->sdl_target); res = SDL_RenderReadPixels(r, NULL, 0, ge->raw_target, 256*4); // "convert" the raw pixel stream to ASCII art on caca canevas caca_set_dither_gamma(ge->d, 1.0); if ( res == 0 ) caca_dither_bitmap(cv, 0, 0, w, h, ge->d, ge->raw_target); return 0; } int scene01_next_sdl(graphical_env_t *ge, scene01_env_t *se) { return 0; } int scene01_next_caca(graphical_env_t *ge, scene01_env_t *se) { // Shorthands caca_canvas_t *cv = ge->cv; int w = ge->w, h = ge->h; Uint32 frame = ge->sc_framecount; caca_set_color_ansi(cv, CACA_WHITE, CACA_BLACK); caca_put_str(cv, (w-17)/2, h/2, "This is a message"); if ( frame >= 300 ) { return 1; } return 0; }