├── .gitignore ├── CMakeLists.txt ├── Changelog ├── INSTALL ├── LICENSE ├── LIMITATIONS ├── Makefile ├── README ├── examples ├── CMakeLists.txt ├── Makefile ├── Makefile~ ├── gears.c └── triangle.c ├── include ├── GL │ ├── gl.h │ └── glu.h ├── zbuffer.h └── zfeatures.h ├── makeinclude └── src ├── CMakeLists.txt ├── Makefile ├── api.c ├── arrays.c ├── clear.c ├── clip.c ├── error.c ├── get.c ├── glu.c ├── image_util.c ├── init.c ├── light.c ├── list.c ├── matrix.c ├── memory.c ├── misc.c ├── msghandling.c ├── msghandling.h ├── opinfo.h ├── oscontext.c ├── oscontext.h ├── select.c ├── specbuf.c ├── specbuf.h ├── texture.c ├── vertex.c ├── zbuffer.c ├── zdither.c ├── zgl.h ├── zline.c ├── zline.h ├── zmath.c ├── zmath.h ├── ztriangle.c └── ztriangle.h /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(TinySDGL) 2 | cmake_minimum_required(VERSION 2.8) 3 | include_directories("${TinySDGL_SOURCE_DIR}/include/") 4 | add_subdirectory(src) 5 | add_subdirectory(examples) 6 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | version 0.5/TinySDGL: 2 | - cleanup of platform specific files not related to the core (Gerald Franz) 3 | - adaption of the gears example to SDL (Gerald Franz) 4 | - added BYTE_ORDER define in zfeatures.h (Gerald Franz) 5 | - moved zfeatures.h and zbuffer.h to include directory (Gerald Franz) 6 | - fixed few compiler warnings in the src directory (Gerald Franz) 7 | 8 | version 0.4: 9 | - added 24/32 bit rendering support (Olivier Landemarre - F. Bellard) 10 | - fixed GL_TRIANGLE_STRIP (Olivier Landemarre) 11 | - added gl_malloc, gl_free, gl_zalloc wrappers (Olivier Landemarre) 12 | 13 | version 0.3: 14 | - added NanoX API (nglx) (F. Bellard) 15 | - added gears example and unified GUI in examples (F. Bellard) 16 | - added TGL_FEATURE_RENDER_BITS so that it will be possible to render 17 | natively in 15/16/24 or 32 bits. (F. Bellard) 18 | - interpolated lines (Olivier Landemarre) 19 | - fast no shading case (Olivier Landemarre) 20 | - fast no projection case (Olivier Landemarre) 21 | 22 | version 0.2: Fabrice Bellard 23 | - added 24/32 bpp support. Added some features.h ifdefs. 24 | - fixed some error reporting cases in the examples 25 | - endianness is deduced from the glibc (BYTE_ORDER macro) 26 | 27 | version 0.19: Peder Blekken 28 | - new files BeOS/* src/msghandling.*, src/arrays.*, src/oscontext.c 29 | include/GL/oscontext.h src/features.h 30 | - added support for BeOS, see README.BEOS 31 | - added support for drawing convex polygons with unlimited # of vertices 32 | - added support for GL_LIGHT_MODEL_TWO_SIDE 33 | - added generic rotation code for glopRotate 34 | - added support for opengl 1.1 arrays 35 | - added support for glPolygonOffset, not implemented. 36 | - added glGetFloatv, limited support. 37 | - added some pnames for glGetIntegerv 38 | - added some empty functions in include/GL/gl.h to compile VRMLView 39 | - added GL_VERSION_1_1 define in include/GL/gl.h 40 | - fixed "bug" when context->gl_resize_viewport is not set. 41 | - fixed bug in glBindTexture (didn't accept texture object 0) 42 | 43 | version 0.1: 44 | - Initial revision, Fabrice Bellard 45 | 46 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation: 2 | 3 | - Edit makeinclude and change what is needed. You can also look at 4 | src/zfeatures.h to change very specific details (only useful to tune 5 | TinySDGL to your needs). You can link the examples with either OpenGL, 6 | Mesa or TinySDGL. 7 | 8 | - Type 'make'. The library 'libTinySDGL.a' is copied into './lib'. The 9 | examples are build in './examples'. Only the directories './lib' and 10 | './include' are needed to use TinySDGL from another program. 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright notice: 2 | 3 | (C) 1997-1998 Fabrice Bellard 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any damages 7 | arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it 11 | freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software 15 | in a product, an acknowledgment in the product and its documentation 16 | *is* required. 17 | 2. Altered source versions must be plainly marked as such, and must not be 18 | misrepresented as being the original software. 19 | 3. This notice may not be removed or altered from any source distribution. 20 | 21 | If you redistribute modified sources, I would appreciate that you 22 | include in the files history information documenting your changes. 23 | -------------------------------------------------------------------------------- /LIMITATIONS: -------------------------------------------------------------------------------- 1 | 2 | Here are listed the functions that TinyGL/TinySDGL understand with the known 3 | limitations. The non mentioned functions are *not* implemented and 4 | must not be used. 5 | 6 | 7 | ************ glEnable / glDisable 8 | 9 | - The following flags are handled: 10 | 11 | GL_CULL_FACE, GL_LIGHTING, GL_COLOR_MATERIAL, GL_TEXTURE_2D, GL_NORMALIZE, 12 | GL_LIGHTx, GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_POINT, 13 | GL_POLYGON_OFFSET_LINE 14 | 15 | 16 | - GL_DEPTH_TEST is accepted, but it is only used for lines. For all 17 | other primitives, Z buffer use is assumed. The DepthMode is 18 | hardcoded as GL_LESS (OpenGL default). 19 | 20 | ************ glShadeModel 21 | 22 | OK. 23 | 24 | ************ glCullFace 25 | 26 | OK. 27 | 28 | ************ glPolygonMode 29 | 30 | OK. 31 | 32 | ************ glBegin 33 | 34 | No tests are performed to prevent some functions of being executed 35 | between glBegin/glEnd. 36 | 37 | ************ glEnd 38 | 39 | OK. 40 | 41 | ************ glVertex 42 | 43 | Some prototypes are not implemented. 44 | 45 | 46 | ************ glColor 47 | 48 | Some prototypes are not implemented. 49 | 50 | ************ glNormal 51 | 52 | Some prototypes are not implemented. 53 | 54 | ************ glTexCoord 55 | 56 | - Some prototypes are not implemented. 57 | 58 | - The Matrix transformation is not applied yet. 59 | 60 | ************ glEdgeFlag 61 | 62 | OK. The edge handling has to be tested, although it is not much useful 63 | in TinyGL. 64 | 65 | ************ glMatrixMode / glLoadMatrixf / glLoadIdentity / glMultMatrixf / 66 | glPushMatrix / glPopMatrix / glRotatef / glTranslatef / glScalef / 67 | glFrustum 68 | 69 | - The prototypes with doubles are not implemented. 70 | 71 | ************ glViewport 72 | 73 | GlViewport calls a function pointers to tell glx (or another display 74 | system) to resize the Z buffer and the ximage. Made optional in 75 | version 0.2. 76 | 77 | ************ glGenLists / glIsList / glNewList / glEndList / glCallList 78 | 79 | OK. 80 | 81 | ************ glClear / glClearColor / glClearDepth 82 | 83 | The whole zbuffer and the colors are cleared in any case. The clear color 84 | can be redefined, by *not* the initial z value. 85 | 86 | ************ glRenderMode 87 | 88 | Only the modes GL_RENDER and GL_SELECT are implemented. 89 | 90 | ************ glSelectBuffer / glInitNames / glPushName / glPopName / glLoadName 91 | 92 | OK. 93 | 94 | ************ glGenTextures / glDeleteTextures / glBindTexture 95 | 96 | OK. These functions should be used to get the maximum performance with 97 | TinyGL. 98 | 99 | ************ glTexImage2D 100 | 101 | The function accepts only RGB UNSIGNED_BYTES bitmaps. They are 102 | internally resized to 256x256 so you'd better use that size. No 103 | mipmapping is implemented although it will come if asked. No borders 104 | are implemented. 105 | 106 | ************ glTexEnvi 107 | 108 | The only supported mode is GL_DECAL, although others are planned if 109 | asked. 110 | 111 | 112 | ************ glTexParameteri 113 | 114 | The other prototypes are not implemented. Only the follwing mode are 115 | implemented: 116 | 117 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 118 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 119 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 120 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 121 | 122 | ************ glPixelStorei 123 | 124 | The pixels are always byte aligned. 125 | 126 | ************ glMaterialfv / glMaterialf / glColorMaterial 127 | 128 | OK. 129 | 130 | 131 | ************ glLightfv / glLightf / glLightModeli / glLightModelfv 132 | 133 | OK. The OpenGL lighting is implemented but not optimized. 134 | 135 | 136 | ************ glFlush 137 | 138 | Ignored. 139 | 140 | ************ glHint 141 | 142 | Ignored. 143 | 144 | ************ glGetIntegerv 145 | 146 | - only GL_VIEWPORT, GL_MAX_MODELVIEW_STACK_DEPTH, 147 | GL_MAX_PROJECTION_STACK_DEPTH, GL_MAX_LIGHTS, GL_MAX_TEXTURE_SIZE, 148 | GL_MAX_TEXTURE_STACK_DEPTH 149 | 150 | ************ glGetIntegerv 151 | 152 | - only GL_TEXTURE_MATRIX, GL_PROJECTION_MATRIX, GL_MODELVIEW_MATRIX, 153 | GL_LINE_WIDTH, GL_LINE_WIDTH_RANGE, GL_POINT_SIZE, GL_POINT_SIZE_RANGE 154 | 155 | ************ glPolygonOffset 156 | 157 | - only API implemented. 158 | 159 | ************ glEnableClientState, glDisableClientState, 160 | 161 | - No support for GL_INDEX_ARRAY_POINTER or GL_EDGE_FLAG_ARRAY_POINTER 162 | 163 | ************ glVertexPointer, glNormalPointer, 164 | glColorPointer, glTexureCoordPointer 165 | 166 | - OK 167 | 168 | ------------------------------------------------------------------------------ 169 | 170 | TinyGL GLX emulation: 171 | 172 | - not available in TinySDGL. Use original TinyGL for that. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include makeinclude 2 | 3 | all: 4 | ( for f in $(DIRS); do ( cd $$f ; make all ) || exit 1 ; done ) 5 | 6 | clean: 7 | rm -f *~ lib/libTinySDGL.a lib/libTinyGLU.a include/GL/*~ TAGS 8 | ( for f in $(DIRS); do ( cd $$f ; make clean ; ) done ) 9 | 10 | install: 11 | ( for f in $(DIRS); do ( cd $$f ; make install ; ) done ) 12 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | TinyGL 0.4 (c) 1997-2002 Fabrice Bellard. 2 | TinySDGL 0.5, 2005 a port to libSDL by Gerald Franz (gfz@o2online.de). 3 | 4 | General Description: 5 | -------------------- 6 | 7 | TinyGL is intended to be a very small implementation of a subset of 8 | OpenGL* for embedded systems or games. It is a software only 9 | implementation. Only the main OpenGL calls are implemented. All the 10 | calls I considered not important are simply *not implemented*. 11 | 12 | The main strength of TinyGL is that it is fast and simple because it 13 | has not to be exactly compatible with OpenGL. In particular, the 14 | texture mapping and the geometrical transformations are very fast. 15 | 16 | The main features of TinyGL are: 17 | 18 | - Header compatible with OpenGL (the headers are adapted from the very good 19 | Mesa by Brian Paul et al.) 20 | 21 | - Zlib-like licence for easy integration in commercial designs (read 22 | the LICENCE file). 23 | 24 | - Examples that show the integration into the platform-independent 25 | libSDL (http://www.libsdl.org) 26 | 27 | - Easy porting to further platforms, since all platform-specific code has 28 | been moved from the core library into the examples. 29 | 30 | - OpenGL like lighting. 31 | 32 | - Complete OpenGL selection mode handling for object picking. 33 | 34 | - 16 bit Z buffer. 16/24/32 bit RGB rendering. High speed dithering to 35 | paletted 8 bits if needed. High speed conversion to 24 bit packed 36 | pixel or 32 bit RGBA if needed. 37 | 38 | - Fast Gouraud shadding optimized for 16 bit RGB. 39 | 40 | - Fast texture mapping capabilities, with perspective correction and 41 | texture objects. 42 | 43 | - 32 bit float only arithmetic. 44 | 45 | - Very small: compiled (and stripped) code size of about 40 kB on x86. 46 | The file include/zfeatures.h can be used to remove some unused 47 | features from TinyGL. 48 | 49 | - C sources for GCC on 32/64 bit architectures. It has been tested 50 | succesfully on x86-Linux and MS Windows. 51 | 52 | Examples: 53 | --------- 54 | 55 | I took three simple examples from the Mesa package to test the main 56 | functions of TinyGL. You can link them to either TinyGL, Mesa or any 57 | other OpenGL implementation. 58 | 59 | - texobj illustrates the use of texture objects. Its shows the speed 60 | of TinyGL in this case (example not included in TinySDGL). 61 | 62 | - You can download and compile the VReng project to see that TinyGL 63 | has been successfully used in a big project 64 | (http://www-inf.enst.fr/vreng). 65 | 66 | Architecture: 67 | ------------- 68 | 69 | TinyGL is made up four main modules: 70 | 71 | - Mathematical routines (zmath). 72 | 73 | - OpenGL-like emulation (zgl). 74 | 75 | - Z buffer and rasterisation (zbuffer). 76 | 77 | To use TinySDGL in a further system, you should look at the examples 78 | and replace the SDL specific code by corresponding commands. 79 | 80 | Notes - limitations: 81 | -------------------- 82 | 83 | - 24 BIT packed pixel format seems not to work correctly under libSDL. 84 | 85 | - See the file 'LIMITATIONS' to see the current functions supported by the API. 86 | 87 | - Multithreading could be easily implemented since no global state 88 | is maintained. The library gets the current context with a function 89 | which can be modified. 90 | 91 | - Lightening is not very fast. I suppose that in most games the 92 | lightening is computed by the 3D engine. 93 | 94 | - Some changes are needed for 64 bit pointers for the handling of 95 | arrays of float with the GLParam union. 96 | 97 | - No user clipping planes are supported. 98 | 99 | - No color index mode (no longer useful !) 100 | 101 | - The mipmapping is not implemented. 102 | 103 | - The perspecture correction in the mapping code does not use W but 104 | 1/Z. In any 'normal scene' it should work. 105 | 106 | Why ? 107 | ----- 108 | 109 | TinyGL was developed as a student project for a Virtual Reality 110 | network system called VReng (see the VReng home page at 111 | http://www-inf.enst.fr/vreng). 112 | 113 | At that time (January 1997), my initial project was to write my own 3D 114 | rasterizer based on some old sources I wrote. But I realized that it 115 | would be better to use OpenGL to work on any platform. My problem was 116 | that I wanted to use texture mapping which was (and is still) quite 117 | slower on many software OpenGL implementation. I could have modified 118 | Mesa to suit my needs, but I really wanted to use my old sources for 119 | that project. 120 | 121 | I finally decided to use the same syntax as OpenGL but with my own 122 | libraries, thinking that later it could ease the porting of VReng to 123 | OpenGL. 124 | 125 | Now VReng is at last compatible with OpenGL, and I managed to patch 126 | TinyGL so that VReng can still work with it without any modifications. 127 | 128 | Since TinyGL may be useful for some people, especially in the world of 129 | embedded designs, I decided to release it 'as is', otherwise, it would 130 | have been lost on my hard disk ! 131 | 132 | ------------------------------------------------------------------------------ 133 | * OpenGL(R) is a registered trademark of Silicon Graphics, Inc. 134 | ------------------------------------------------------------------------------ 135 | Fabrice Bellard. (Minor changes by Gerald Franz) 136 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FIND_PACKAGE(SDL REQUIRED) 2 | include_directories(${SDL_INCLUDE_DIR}) 3 | 4 | add_executable(TinySDGLGears gears) 5 | target_link_libraries(TinySDGLGears TinySDGL_shared ${SDL_LIBRARY}) 6 | 7 | add_executable(TinySDGLTriangle triangle) 8 | target_link_libraries(TinySDGLTriangle TinySDGL_shared ${SDL_LIBRARY}) 9 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | include ../makeinclude 2 | 3 | PROGS = gears triangle 4 | 5 | all: $(PROGS) 6 | 7 | clean: 8 | rm -f core *.o *~ $(PROGS) 9 | 10 | gears: gears.o 11 | $(CC) $(LFLAGS) $^ -o $@ $(GL_LIBS) $(UI_LIBS) -lm 12 | 13 | triangle: triangle.o 14 | $(CC) $(LFLAGS) $^ -o $@ -lTinyGLU $(GL_LIBS) $(UI_LIBS) -lm 15 | 16 | .c.o: 17 | $(CC) $(CFLAGS) $(GL_INCLUDES) $(UI_INCLUDES) -c $*.c 18 | -------------------------------------------------------------------------------- /examples/Makefile~: -------------------------------------------------------------------------------- 1 | include ../makeinclude 2 | 3 | PROGS = mElite gears triangle 4 | 5 | all: $(PROGS) 6 | 7 | clean: 8 | rm -f core *.o *~ $(PROGS) 9 | 10 | gears: gears.o 11 | $(CC) $(LFLAGS) $^ -o $@ $(GL_LIBS) $(UI_LIBS) -lm 12 | 13 | triangle: triangle.o 14 | $(CC) $(LFLAGS) $^ -o $@ -lTinyGLU $(GL_LIBS) $(UI_LIBS) -lm 15 | 16 | mElite: mElite.o 17 | $(CC) $(LFLAGS) $^ -o $@ -lTinyGLU $(GL_LIBS) $(UI_LIBS) -lm 18 | 19 | .c.o: 20 | $(CC) $(CFLAGS) $(GL_INCLUDES) $(UI_INCLUDES) -c $*.c 21 | -------------------------------------------------------------------------------- /examples/gears.c: -------------------------------------------------------------------------------- 1 | /* sdlGears.c */ 2 | /* 3 | * 3-D gear wheels by Brian Paul. This program is in the public domain. 4 | * 5 | * ported to libSDL/TinyGL by Gerald Franz (gfz@o2online.de) 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef M_PI 18 | # define M_PI 3.14159265 19 | #endif 20 | 21 | 22 | /* 23 | * Draw a gear wheel. You'll probably want to call this function when 24 | * building a display list since we do a lot of trig here. 25 | * 26 | * Input: inner_radius - radius of hole at center 27 | * outer_radius - radius at center of teeth 28 | * width - width of gear 29 | * teeth - number of teeth 30 | * tooth_depth - depth of tooth 31 | */ 32 | static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width, 33 | GLint teeth, GLfloat tooth_depth ) 34 | { 35 | GLint i; 36 | GLfloat r0, r1, r2; 37 | GLfloat angle, da; 38 | GLfloat u, v, len; 39 | 40 | r0 = inner_radius; 41 | r1 = outer_radius - tooth_depth/2.0; 42 | r2 = outer_radius + tooth_depth/2.0; 43 | 44 | da = 2.0*M_PI / teeth / 4.0; 45 | 46 | glShadeModel( GL_FLAT ); 47 | 48 | glNormal3f( 0.0, 0.0, 1.0 ); 49 | 50 | /* draw front face */ 51 | glBegin( GL_QUAD_STRIP ); 52 | for (i=0;i<=teeth;i++) { 53 | angle = i * 2.0*M_PI / teeth; 54 | glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 ); 55 | glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 ); 56 | glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 ); 57 | glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 ); 58 | } 59 | glEnd(); 60 | 61 | /* draw front sides of teeth */ 62 | glBegin( GL_QUADS ); 63 | da = 2.0*M_PI / teeth / 4.0; 64 | for (i=0;iformat->BitsPerPixel ) { 233 | case 8: 234 | fprintf(stderr,"ERROR: Palettes are currently not supported.\n"); 235 | return 1; 236 | case 16: 237 | pitch = screen->pitch; 238 | mode = ZB_MODE_5R6G5B; 239 | break; 240 | case 24: 241 | pitch = ( screen->pitch * 2 ) / 3; 242 | mode = ZB_MODE_RGB24; 243 | break; 244 | case 32: 245 | pitch = screen->pitch / 2; 246 | mode = ZB_MODE_RGBA; 247 | break; 248 | default: 249 | return 1; 250 | break; 251 | } 252 | ZBuffer *frameBuffer = ZB_open( winSizeX, winSizeY, mode, 0, 0, 0, 0); 253 | glInit( frameBuffer ); 254 | 255 | // initialize GL: 256 | glClearColor (0.0, 0.0, 0.0, 0.0); 257 | glViewport (0, 0, winSizeX, winSizeY); 258 | glEnable(GL_DEPTH_TEST); 259 | GLfloat h = (GLfloat) winSizeY / (GLfloat) winSizeX; 260 | glMatrixMode(GL_PROJECTION); 261 | glLoadIdentity(); 262 | glFrustum( -1.0, 1.0, -h, h, 5.0, 60.0 ); 263 | glMatrixMode(GL_MODELVIEW); 264 | glLoadIdentity(); 265 | glTranslatef( 0.0, 0.0, -45.0 ); 266 | 267 | initScene(); 268 | 269 | // variables for timing: 270 | unsigned int frames=0; 271 | unsigned int tNow=SDL_GetTicks(); 272 | unsigned int tLastFps=tNow; 273 | 274 | // main loop: 275 | int isRunning=1; 276 | while(isRunning) { 277 | ++frames; 278 | tNow=SDL_GetTicks(); 279 | // do event handling: 280 | SDL_Event evt; 281 | while( SDL_PollEvent( &evt ) ) switch(evt.type) { 282 | case SDL_KEYDOWN: 283 | switch(evt.key.keysym.sym) { 284 | case SDLK_UP: 285 | view_rotx += 5.0; 286 | break; 287 | case SDLK_DOWN: 288 | view_rotx -= 5.0; 289 | break; 290 | case SDLK_LEFT: 291 | view_roty += 5.0; 292 | break; 293 | case SDLK_RIGHT: 294 | view_roty -= 5.0; 295 | break; 296 | case SDLK_ESCAPE : 297 | case SDLK_q : 298 | isRunning=0; 299 | default: 300 | break; 301 | } 302 | break; 303 | case SDL_QUIT: 304 | isRunning=0; 305 | break; 306 | } 307 | 308 | // draw scene: 309 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 310 | draw(); 311 | 312 | // swap buffers: 313 | if ( SDL_MUSTLOCK(screen) && (SDL_LockSurface(screen)<0) ) { 314 | fprintf(stderr, "SDL ERROR: Can't lock screen: %s\n", SDL_GetError()); 315 | return 1; 316 | } 317 | ZB_copyFrameBuffer(frameBuffer, screen->pixels, pitch); 318 | if ( SDL_MUSTLOCK(screen) ) SDL_UnlockSurface(screen); 319 | SDL_Flip(screen); 320 | 321 | // check for error conditions: 322 | char* sdl_error = SDL_GetError( ); 323 | if( sdl_error[0] != '\0' ) { 324 | fprintf(stderr,"SDL ERROR: \"%s\"\n",sdl_error); 325 | SDL_ClearError(); 326 | } 327 | // update fps: 328 | if(tNow>=tLastFps+5000) { 329 | printf("%i frames in %f secs, %f frames per second.\n",frames,(float)(tNow-tLastFps)*0.001f,(float)frames*1000.0f/(float)(tNow-tLastFps)); 330 | tLastFps=tNow; 331 | frames=0; 332 | } 333 | } 334 | printf("%i frames in %f secs, %f frames per second.\n",frames,(float)(tNow-tLastFps)*0.001f,(float)frames*1000.0f/(float)(tNow-tLastFps)); 335 | // cleanup: 336 | ZB_close(frameBuffer); 337 | if(SDL_WasInit(SDL_INIT_VIDEO)) 338 | SDL_QuitSubSystem(SDL_INIT_VIDEO); 339 | SDL_Quit(); 340 | return 0; 341 | } 342 | -------------------------------------------------------------------------------- /examples/triangle.c: -------------------------------------------------------------------------------- 1 | // adapted from GLFW, glfw.sf.net 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char **argv) { 9 | // initialize SDL video: 10 | int winSizeX=640; 11 | int winSizeY=480; 12 | if(SDL_Init(SDL_INIT_VIDEO)<0) { 13 | fprintf(stderr,"ERROR: cannot initialize SDL video.\n"); 14 | return 1; 15 | } 16 | SDL_Surface* screen = NULL; 17 | if((screen=SDL_SetVideoMode( winSizeX, winSizeY, 32, SDL_SWSURFACE)) == 0 ) { 18 | fprintf(stderr,"ERROR: Video mode set failed.\n"); 19 | return 1; 20 | } 21 | 22 | // initialize TinyGL: 23 | unsigned int pitch; 24 | int mode; 25 | switch( screen->format->BitsPerPixel ) { 26 | case 8: 27 | fprintf(stderr,"ERROR: Palettes are currently not supported.\n"); 28 | return 1; 29 | case 16: 30 | pitch = screen->pitch; 31 | mode = ZB_MODE_5R6G5B; 32 | break; 33 | case 24: 34 | pitch = ( screen->pitch * 2 ) / 3; 35 | mode = ZB_MODE_RGB24; 36 | break; 37 | case 32: 38 | pitch = screen->pitch / 2; 39 | mode = ZB_MODE_RGBA; 40 | break; 41 | default: 42 | return 1; 43 | break; 44 | } 45 | ZBuffer *frameBuffer = ZB_open( winSizeX, winSizeY, mode, 0, 0, 0, 0); 46 | glInit( frameBuffer ); 47 | 48 | // set viewport 49 | glViewport( 0, 0, winSizeX, winSizeY); 50 | glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); 51 | 52 | // main loop: 53 | int frames=0; 54 | int x=0; 55 | double t, t0, fps; 56 | char titlestr[ 200 ]; 57 | int running = GL_TRUE; 58 | t0 = (double)SDL_GetTicks()/1000.0; 59 | while( running ) { 60 | // calculate and display FPS (frames per second): 61 | t = (double)SDL_GetTicks()/1000.0; 62 | if( (t-t0) > 1.0 || frames == 0 ) { 63 | fps = (double)frames / (t-t0); 64 | sprintf( titlestr, "Spinning Triangle (%.1f FPS)", fps ); 65 | SDL_WM_SetCaption(titlestr,0); 66 | t0 = t; 67 | frames = 0; 68 | } 69 | ++frames; 70 | 71 | // Clear color buffer 72 | glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 73 | 74 | // Select and setup the projection matrix 75 | glMatrixMode( GL_PROJECTION ); 76 | glLoadIdentity(); 77 | gluPerspective( 65.0f, (GLfloat)winSizeX/(GLfloat)winSizeY, 1.0f, 100.0f ); 78 | 79 | // Select and setup the modelview matrix 80 | glMatrixMode( GL_MODELVIEW ); 81 | glLoadIdentity(); 82 | glRotatef(-90, 1,0,0); 83 | glTranslatef(0,0,-1.0f); 84 | 85 | // Draw a rotating colorful triangle 86 | glTranslatef( 0.0f, 14.0f, 0.0f ); 87 | glRotatef( 0.3*(GLfloat)x + (GLfloat)t*100.0f, 0.0f, 0.0f, 1.0f ); 88 | glBegin( GL_TRIANGLES ); 89 | glColor3f( 1.0f, 0.0f, 0.0f ); 90 | glVertex3f( -5.0f, 0.0f, -4.0f ); 91 | glColor3f( 0.0f, 1.0f, 0.0f ); 92 | glVertex3f( 5.0f, 0.0f, -4.0f ); 93 | glColor3f( 0.0f, 0.0f, 1.0f ); 94 | glVertex3f( 0.0f, 0.0f, 6.0f ); 95 | glEnd(); 96 | 97 | // swap buffers: 98 | if ( SDL_MUSTLOCK(screen) && (SDL_LockSurface(screen)<0) ) { 99 | fprintf(stderr, "SDL ERROR: Can't lock screen: %s\n", SDL_GetError()); 100 | return 1; 101 | } 102 | ZB_copyFrameBuffer(frameBuffer, screen->pixels, pitch); 103 | if ( SDL_MUSTLOCK(screen) ) SDL_UnlockSurface(screen); 104 | SDL_Flip(screen); 105 | 106 | // check if the ESC key was pressed or the window was closed: 107 | SDL_Event evt; 108 | while( SDL_PollEvent( &evt ) ) switch(evt.type) { 109 | case SDL_KEYDOWN: 110 | if(evt.key.keysym.sym==SDLK_ESCAPE) 111 | running=0; 112 | break; 113 | case SDL_QUIT: 114 | running=0; 115 | break; 116 | } 117 | } 118 | // cleanup: 119 | ZB_close(frameBuffer); 120 | if(SDL_WasInit(SDL_INIT_VIDEO)) 121 | SDL_QuitSubSystem(SDL_INIT_VIDEO); 122 | SDL_Quit(); 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /include/GL/gl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The following constants come from Mesa 3 | */ 4 | #ifndef GL_H 5 | #define GL_H 6 | 7 | #define GL_VERSION_1_1 1 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | enum { 14 | /* Boolean values */ 15 | GL_FALSE = 0, 16 | GL_TRUE = 1, 17 | 18 | /* Data types */ 19 | GL_BYTE = 0x1400, 20 | GL_UNSIGNED_BYTE = 0x1401, 21 | GL_SHORT = 0x1402, 22 | GL_UNSIGNED_SHORT = 0x1403, 23 | GL_INT = 0x1404, 24 | GL_UNSIGNED_INT = 0x1405, 25 | GL_FLOAT = 0x1406, 26 | GL_DOUBLE = 0x140A, 27 | GL_2_BYTES = 0x1407, 28 | GL_3_BYTES = 0x1408, 29 | GL_4_BYTES = 0x1409, 30 | 31 | /* Primitives */ 32 | GL_LINES = 0x0001, 33 | GL_POINTS = 0x0000, 34 | GL_LINE_STRIP = 0x0003, 35 | GL_LINE_LOOP = 0x0002, 36 | GL_TRIANGLES = 0x0004, 37 | GL_TRIANGLE_STRIP = 0x0005, 38 | GL_TRIANGLE_FAN = 0x0006, 39 | GL_QUADS = 0x0007, 40 | GL_QUAD_STRIP = 0x0008, 41 | GL_POLYGON = 0x0009, 42 | GL_EDGE_FLAG = 0x0B43, 43 | 44 | /* Vertex Arrays */ 45 | GL_VERTEX_ARRAY = 0x8074, 46 | GL_NORMAL_ARRAY = 0x8075, 47 | GL_COLOR_ARRAY = 0x8076, 48 | GL_INDEX_ARRAY = 0x8077, 49 | GL_TEXTURE_COORD_ARRAY = 0x8078, 50 | GL_EDGE_FLAG_ARRAY = 0x8079, 51 | GL_VERTEX_ARRAY_SIZE = 0x807A, 52 | GL_VERTEX_ARRAY_TYPE = 0x807B, 53 | GL_VERTEX_ARRAY_STRIDE = 0x807C, 54 | GL_VERTEX_ARRAY_COUNT = 0x807D, 55 | GL_NORMAL_ARRAY_TYPE = 0x807E, 56 | GL_NORMAL_ARRAY_STRIDE = 0x807F, 57 | GL_NORMAL_ARRAY_COUNT = 0x8080, 58 | GL_COLOR_ARRAY_SIZE = 0x8081, 59 | GL_COLOR_ARRAY_TYPE = 0x8082, 60 | GL_COLOR_ARRAY_STRIDE = 0x8083, 61 | GL_COLOR_ARRAY_COUNT = 0x8084, 62 | GL_INDEX_ARRAY_TYPE = 0x8085, 63 | GL_INDEX_ARRAY_STRIDE = 0x8086, 64 | GL_INDEX_ARRAY_COUNT = 0x8087, 65 | GL_TEXTURE_COORD_ARRAY_SIZE = 0x8088, 66 | GL_TEXTURE_COORD_ARRAY_TYPE = 0x8089, 67 | GL_TEXTURE_COORD_ARRAY_STRIDE = 0x808A, 68 | GL_TEXTURE_COORD_ARRAY_COUNT = 0x808B, 69 | GL_EDGE_FLAG_ARRAY_STRIDE = 0x808C, 70 | GL_EDGE_FLAG_ARRAY_COUNT = 0x808D, 71 | GL_VERTEX_ARRAY_POINTER = 0x808E, 72 | GL_NORMAL_ARRAY_POINTER = 0x808F, 73 | GL_COLOR_ARRAY_POINTER = 0x8090, 74 | GL_INDEX_ARRAY_POINTER = 0x8091, 75 | GL_TEXTURE_COORD_ARRAY_POINTER = 0x8092, 76 | GL_EDGE_FLAG_ARRAY_POINTER = 0x8093, 77 | GL_V2F = 0x2A20, 78 | GL_V3F = 0x2A21, 79 | GL_C4UB_V2F = 0x2A22, 80 | GL_C4UB_V3F = 0x2A23, 81 | GL_C3F_V3F = 0x2A24, 82 | GL_N3F_V3F = 0x2A25, 83 | GL_C4F_N3F_V3F = 0x2A26, 84 | GL_T2F_V3F = 0x2A27, 85 | GL_T4F_V4F = 0x2A28, 86 | GL_T2F_C4UB_V3F = 0x2A29, 87 | GL_T2F_C3F_V3F = 0x2A2A, 88 | GL_T2F_N3F_V3F = 0x2A2B, 89 | GL_T2F_C4F_N3F_V3F = 0x2A2C, 90 | GL_T4F_C4F_N3F_V4F = 0x2A2D, 91 | 92 | /* Matrix Mode */ 93 | GL_MATRIX_MODE = 0x0BA0, 94 | GL_MODELVIEW = 0x1700, 95 | GL_PROJECTION = 0x1701, 96 | GL_TEXTURE = 0x1702, 97 | 98 | /* Points */ 99 | GL_POINT_SMOOTH = 0x0B10, 100 | GL_POINT_SIZE = 0x0B11, 101 | GL_POINT_SIZE_GRANULARITY = 0x0B13, 102 | GL_POINT_SIZE_RANGE = 0x0B12, 103 | 104 | /* Lines */ 105 | GL_LINE_SMOOTH = 0x0B20, 106 | GL_LINE_STIPPLE = 0x0B24, 107 | GL_LINE_STIPPLE_PATTERN = 0x0B25, 108 | GL_LINE_STIPPLE_REPEAT = 0x0B26, 109 | GL_LINE_WIDTH = 0x0B21, 110 | GL_LINE_WIDTH_GRANULARITY = 0x0B23, 111 | GL_LINE_WIDTH_RANGE = 0x0B22, 112 | 113 | /* Polygons */ 114 | GL_POINT = 0x1B00, 115 | GL_LINE = 0x1B01, 116 | GL_FILL = 0x1B02, 117 | GL_CCW = 0x0901, 118 | GL_CW = 0x0900, 119 | GL_FRONT = 0x0404, 120 | GL_BACK = 0x0405, 121 | GL_CULL_FACE = 0x0B44, 122 | GL_CULL_FACE_MODE = 0x0B45, 123 | GL_POLYGON_SMOOTH = 0x0B41, 124 | GL_POLYGON_STIPPLE = 0x0B42, 125 | GL_FRONT_FACE = 0x0B46, 126 | GL_POLYGON_MODE = 0x0B40, 127 | GL_POLYGON_OFFSET_FACTOR = 0x3038, 128 | GL_POLYGON_OFFSET_UNITS = 0x2A00, 129 | GL_POLYGON_OFFSET_POINT = 0x2A01, 130 | GL_POLYGON_OFFSET_LINE = 0x2A02, 131 | GL_POLYGON_OFFSET_FILL = 0x8037, 132 | 133 | /* Display Lists */ 134 | GL_COMPILE = 0x1300, 135 | GL_COMPILE_AND_EXECUTE = 0x1301, 136 | GL_LIST_BASE = 0x0B32, 137 | GL_LIST_INDEX = 0x0B33, 138 | GL_LIST_MODE = 0x0B30, 139 | 140 | /* Depth buffer */ 141 | GL_NEVER = 0x0200, 142 | GL_LESS = 0x0201, 143 | GL_GEQUAL = 0x0206, 144 | GL_LEQUAL = 0x0203, 145 | GL_GREATER = 0x0204, 146 | GL_NOTEQUAL = 0x0205, 147 | GL_EQUAL = 0x0202, 148 | GL_ALWAYS = 0x0207, 149 | GL_DEPTH_TEST = 0x0B71, 150 | GL_DEPTH_BITS = 0x0D56, 151 | GL_DEPTH_CLEAR_VALUE = 0x0B73, 152 | GL_DEPTH_FUNC = 0x0B74, 153 | GL_DEPTH_RANGE = 0x0B70, 154 | GL_DEPTH_WRITEMASK = 0x0B72, 155 | GL_DEPTH_COMPONENT = 0x1902, 156 | 157 | /* Lighting */ 158 | GL_LIGHTING = 0x0B50, 159 | GL_LIGHT0 = 0x4000, 160 | GL_LIGHT1 = 0x4001, 161 | GL_LIGHT2 = 0x4002, 162 | GL_LIGHT3 = 0x4003, 163 | GL_LIGHT4 = 0x4004, 164 | GL_LIGHT5 = 0x4005, 165 | GL_LIGHT6 = 0x4006, 166 | GL_LIGHT7 = 0x4007, 167 | GL_SPOT_EXPONENT = 0x1205, 168 | GL_SPOT_CUTOFF = 0x1206, 169 | GL_CONSTANT_ATTENUATION = 0x1207, 170 | GL_LINEAR_ATTENUATION = 0x1208, 171 | GL_QUADRATIC_ATTENUATION = 0x1209, 172 | GL_AMBIENT = 0x1200, 173 | GL_DIFFUSE = 0x1201, 174 | GL_SPECULAR = 0x1202, 175 | GL_SHININESS = 0x1601, 176 | GL_EMISSION = 0x1600, 177 | GL_POSITION = 0x1203, 178 | GL_SPOT_DIRECTION = 0x1204, 179 | GL_AMBIENT_AND_DIFFUSE = 0x1602, 180 | GL_COLOR_INDEXES = 0x1603, 181 | GL_LIGHT_MODEL_TWO_SIDE = 0x0B52, 182 | GL_LIGHT_MODEL_LOCAL_VIEWER = 0x0B51, 183 | GL_LIGHT_MODEL_AMBIENT = 0x0B53, 184 | GL_FRONT_AND_BACK = 0x0408, 185 | GL_SHADE_MODEL = 0x0B54, 186 | GL_FLAT = 0x1D00, 187 | GL_SMOOTH = 0x1D01, 188 | GL_COLOR_MATERIAL = 0x0B57, 189 | GL_COLOR_MATERIAL_FACE = 0x0B55, 190 | GL_COLOR_MATERIAL_PARAMETER = 0x0B56, 191 | GL_NORMALIZE = 0x0BA1, 192 | 193 | /* User clipping planes */ 194 | GL_CLIP_PLANE0 = 0x3000, 195 | GL_CLIP_PLANE1 = 0x3001, 196 | GL_CLIP_PLANE2 = 0x3002, 197 | GL_CLIP_PLANE3 = 0x3003, 198 | GL_CLIP_PLANE4 = 0x3004, 199 | GL_CLIP_PLANE5 = 0x3005, 200 | 201 | /* Accumulation buffer */ 202 | GL_ACCUM_RED_BITS = 0x0D58, 203 | GL_ACCUM_GREEN_BITS = 0x0D59, 204 | GL_ACCUM_BLUE_BITS = 0x0D5A, 205 | GL_ACCUM_ALPHA_BITS = 0x0D5B, 206 | GL_ACCUM_CLEAR_VALUE = 0x0B80, 207 | GL_ACCUM = 0x0100, 208 | GL_ADD = 0x0104, 209 | GL_LOAD = 0x0101, 210 | GL_MULT = 0x0103, 211 | GL_RETURN = 0x0102, 212 | 213 | /* Alpha testing */ 214 | GL_ALPHA_TEST = 0x0BC0, 215 | GL_ALPHA_TEST_REF = 0x0BC2, 216 | GL_ALPHA_TEST_FUNC = 0x0BC1, 217 | 218 | /* Blending */ 219 | GL_BLEND = 0x0BE2, 220 | GL_BLEND_SRC = 0x0BE1, 221 | GL_BLEND_DST = 0x0BE0, 222 | GL_ZERO = 0, 223 | GL_ONE = 1, 224 | GL_SRC_COLOR = 0x0300, 225 | GL_ONE_MINUS_SRC_COLOR = 0x0301, 226 | GL_DST_COLOR = 0x0306, 227 | GL_ONE_MINUS_DST_COLOR = 0x0307, 228 | GL_SRC_ALPHA = 0x0302, 229 | GL_ONE_MINUS_SRC_ALPHA = 0x0303, 230 | GL_DST_ALPHA = 0x0304, 231 | GL_ONE_MINUS_DST_ALPHA = 0x0305, 232 | GL_SRC_ALPHA_SATURATE = 0x0308, 233 | GL_CONSTANT_COLOR = 0x8001, 234 | GL_ONE_MINUS_CONSTANT_COLOR = 0x8002, 235 | GL_CONSTANT_ALPHA = 0x8003, 236 | GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004, 237 | 238 | /* Render Mode */ 239 | GL_FEEDBACK = 0x1C01, 240 | GL_RENDER = 0x1C00, 241 | GL_SELECT = 0x1C02, 242 | 243 | /* Feedback */ 244 | GL_2D = 0x0600, 245 | GL_3D = 0x0601, 246 | GL_3D_COLOR = 0x0602, 247 | GL_3D_COLOR_TEXTURE = 0x0603, 248 | GL_4D_COLOR_TEXTURE = 0x0604, 249 | GL_POINT_TOKEN = 0x0701, 250 | GL_LINE_TOKEN = 0x0702, 251 | GL_LINE_RESET_TOKEN = 0x0707, 252 | GL_POLYGON_TOKEN = 0x0703, 253 | GL_BITMAP_TOKEN = 0x0704, 254 | GL_DRAW_PIXEL_TOKEN = 0x0705, 255 | GL_COPY_PIXEL_TOKEN = 0x0706, 256 | GL_PASS_THROUGH_TOKEN = 0x0700, 257 | 258 | /* Fog */ 259 | GL_FOG = 0x0B60, 260 | GL_FOG_MODE = 0x0B65, 261 | GL_FOG_DENSITY = 0x0B62, 262 | GL_FOG_COLOR = 0x0B66, 263 | GL_FOG_INDEX = 0x0B61, 264 | GL_FOG_START = 0x0B63, 265 | GL_FOG_END = 0x0B64, 266 | GL_LINEAR = 0x2601, 267 | GL_EXP = 0x0800, 268 | GL_EXP2 = 0x0801, 269 | 270 | /* Logic Ops */ 271 | GL_LOGIC_OP = 0x0BF1, 272 | GL_LOGIC_OP_MODE = 0x0BF0, 273 | GL_CLEAR = 0x1500, 274 | GL_SET = 0x150F, 275 | GL_COPY = 0x1503, 276 | GL_COPY_INVERTED = 0x150C, 277 | GL_NOOP = 0x1505, 278 | GL_INVERT = 0x150A, 279 | GL_AND = 0x1501, 280 | GL_NAND = 0x150E, 281 | GL_OR = 0x1507, 282 | GL_NOR = 0x1508, 283 | GL_XOR = 0x1506, 284 | GL_EQUIV = 0x1509, 285 | GL_AND_REVERSE = 0x1502, 286 | GL_AND_INVERTED = 0x1504, 287 | GL_OR_REVERSE = 0x150B, 288 | GL_OR_INVERTED = 0x150D, 289 | 290 | /* Stencil */ 291 | GL_STENCIL_TEST = 0x0B90, 292 | GL_STENCIL_WRITEMASK = 0x0B98, 293 | GL_STENCIL_BITS = 0x0D57, 294 | GL_STENCIL_FUNC = 0x0B92, 295 | GL_STENCIL_VALUE_MASK = 0x0B93, 296 | GL_STENCIL_REF = 0x0B97, 297 | GL_STENCIL_FAIL = 0x0B94, 298 | GL_STENCIL_PASS_DEPTH_PASS = 0x0B96, 299 | GL_STENCIL_PASS_DEPTH_FAIL = 0x0B95, 300 | GL_STENCIL_CLEAR_VALUE = 0x0B91, 301 | GL_STENCIL_INDEX = 0x1901, 302 | GL_KEEP = 0x1E00, 303 | GL_REPLACE = 0x1E01, 304 | GL_INCR = 0x1E02, 305 | GL_DECR = 0x1E03, 306 | 307 | /* Buffers, Pixel Drawing/Reading */ 308 | GL_NONE = 0, 309 | GL_LEFT = 0x0406, 310 | GL_RIGHT = 0x0407, 311 | /*GL_FRONT = 0x0404, */ 312 | /*GL_BACK = 0x0405, */ 313 | /*GL_FRONT_AND_BACK = 0x0408, */ 314 | GL_FRONT_LEFT = 0x0400, 315 | GL_FRONT_RIGHT = 0x0401, 316 | GL_BACK_LEFT = 0x0402, 317 | GL_BACK_RIGHT = 0x0403, 318 | GL_AUX0 = 0x0409, 319 | GL_AUX1 = 0x040A, 320 | GL_AUX2 = 0x040B, 321 | GL_AUX3 = 0x040C, 322 | GL_COLOR_INDEX = 0x1900, 323 | GL_RED = 0x1903, 324 | GL_GREEN = 0x1904, 325 | GL_BLUE = 0x1905, 326 | GL_ALPHA = 0x1906, 327 | GL_LUMINANCE = 0x1909, 328 | GL_LUMINANCE_ALPHA = 0x190A, 329 | GL_ALPHA_BITS = 0x0D55, 330 | GL_RED_BITS = 0x0D52, 331 | GL_GREEN_BITS = 0x0D53, 332 | GL_BLUE_BITS = 0x0D54, 333 | GL_INDEX_BITS = 0x0D51, 334 | GL_SUBPIXEL_BITS = 0x0D50, 335 | GL_AUX_BUFFERS = 0x0C00, 336 | GL_READ_BUFFER = 0x0C02, 337 | GL_DRAW_BUFFER = 0x0C01, 338 | GL_DOUBLEBUFFER = 0x0C32, 339 | GL_STEREO = 0x0C33, 340 | GL_BITMAP = 0x1A00, 341 | GL_COLOR = 0x1800, 342 | GL_DEPTH = 0x1801, 343 | GL_STENCIL = 0x1802, 344 | GL_DITHER = 0x0BD0, 345 | GL_RGB = 0x1907, 346 | GL_RGBA = 0x1908, 347 | 348 | /* Implementation limits */ 349 | GL_MAX_LIST_NESTING = 0x0B31, 350 | GL_MAX_ATTRIB_STACK_DEPTH = 0x0D35, 351 | GL_MAX_MODELVIEW_STACK_DEPTH = 0x0D36, 352 | GL_MAX_NAME_STACK_DEPTH = 0x0D37, 353 | GL_MAX_PROJECTION_STACK_DEPTH = 0x0D38, 354 | GL_MAX_TEXTURE_STACK_DEPTH = 0x0D39, 355 | GL_MAX_EVAL_ORDER = 0x0D30, 356 | GL_MAX_LIGHTS = 0x0D31, 357 | GL_MAX_CLIP_PLANES = 0x0D32, 358 | GL_MAX_TEXTURE_SIZE = 0x0D33, 359 | GL_MAX_PIXEL_MAP_TABLE = 0x0D34, 360 | GL_MAX_VIEWPORT_DIMS = 0x0D3A, 361 | GL_MAX_CLIENT_ATTRIB_STACK_DEPTH= 0x0D3B, 362 | 363 | /* Gets */ 364 | GL_ATTRIB_STACK_DEPTH = 0x0BB0, 365 | GL_COLOR_CLEAR_VALUE = 0x0C22, 366 | GL_COLOR_WRITEMASK = 0x0C23, 367 | GL_CURRENT_INDEX = 0x0B01, 368 | GL_CURRENT_COLOR = 0x0B00, 369 | GL_CURRENT_NORMAL = 0x0B02, 370 | GL_CURRENT_RASTER_COLOR = 0x0B04, 371 | GL_CURRENT_RASTER_DISTANCE = 0x0B09, 372 | GL_CURRENT_RASTER_INDEX = 0x0B05, 373 | GL_CURRENT_RASTER_POSITION = 0x0B07, 374 | GL_CURRENT_RASTER_TEXTURE_COORDS = 0x0B06, 375 | GL_CURRENT_RASTER_POSITION_VALID = 0x0B08, 376 | GL_CURRENT_TEXTURE_COORDS = 0x0B03, 377 | GL_INDEX_CLEAR_VALUE = 0x0C20, 378 | GL_INDEX_MODE = 0x0C30, 379 | GL_INDEX_WRITEMASK = 0x0C21, 380 | GL_MODELVIEW_MATRIX = 0x0BA6, 381 | GL_MODELVIEW_STACK_DEPTH = 0x0BA3, 382 | GL_NAME_STACK_DEPTH = 0x0D70, 383 | GL_PROJECTION_MATRIX = 0x0BA7, 384 | GL_PROJECTION_STACK_DEPTH = 0x0BA4, 385 | GL_RENDER_MODE = 0x0C40, 386 | GL_RGBA_MODE = 0x0C31, 387 | GL_TEXTURE_MATRIX = 0x0BA8, 388 | GL_TEXTURE_STACK_DEPTH = 0x0BA5, 389 | GL_VIEWPORT = 0x0BA2, 390 | 391 | 392 | /* Evaluators */ 393 | GL_AUTO_NORMAL = 0x0D80, 394 | GL_MAP1_COLOR_4 = 0x0D90, 395 | GL_MAP1_GRID_DOMAIN = 0x0DD0, 396 | GL_MAP1_GRID_SEGMENTS = 0x0DD1, 397 | GL_MAP1_INDEX = 0x0D91, 398 | GL_MAP1_NORMAL = 0x0D92, 399 | GL_MAP1_TEXTURE_COORD_1 = 0x0D93, 400 | GL_MAP1_TEXTURE_COORD_2 = 0x0D94, 401 | GL_MAP1_TEXTURE_COORD_3 = 0x0D95, 402 | GL_MAP1_TEXTURE_COORD_4 = 0x0D96, 403 | GL_MAP1_VERTEX_3 = 0x0D97, 404 | GL_MAP1_VERTEX_4 = 0x0D98, 405 | GL_MAP2_COLOR_4 = 0x0DB0, 406 | GL_MAP2_GRID_DOMAIN = 0x0DD2, 407 | GL_MAP2_GRID_SEGMENTS = 0x0DD3, 408 | GL_MAP2_INDEX = 0x0DB1, 409 | GL_MAP2_NORMAL = 0x0DB2, 410 | GL_MAP2_TEXTURE_COORD_1 = 0x0DB3, 411 | GL_MAP2_TEXTURE_COORD_2 = 0x0DB4, 412 | GL_MAP2_TEXTURE_COORD_3 = 0x0DB5, 413 | GL_MAP2_TEXTURE_COORD_4 = 0x0DB6, 414 | GL_MAP2_VERTEX_3 = 0x0DB7, 415 | GL_MAP2_VERTEX_4 = 0x0DB8, 416 | GL_COEFF = 0x0A00, 417 | GL_DOMAIN = 0x0A02, 418 | GL_ORDER = 0x0A01, 419 | 420 | /* Hints */ 421 | GL_FOG_HINT = 0x0C54, 422 | GL_LINE_SMOOTH_HINT = 0x0C52, 423 | GL_PERSPECTIVE_CORRECTION_HINT = 0x0C50, 424 | GL_POINT_SMOOTH_HINT = 0x0C51, 425 | GL_POLYGON_SMOOTH_HINT = 0x0C53, 426 | GL_DONT_CARE = 0x1100, 427 | GL_FASTEST = 0x1101, 428 | GL_NICEST = 0x1102, 429 | 430 | /* Scissor box */ 431 | GL_SCISSOR_TEST = 0x0C11, 432 | GL_SCISSOR_BOX = 0x0C10, 433 | 434 | /* Pixel Mode / Transfer */ 435 | GL_MAP_COLOR = 0x0D10, 436 | GL_MAP_STENCIL = 0x0D11, 437 | GL_INDEX_SHIFT = 0x0D12, 438 | GL_INDEX_OFFSET = 0x0D13, 439 | GL_RED_SCALE = 0x0D14, 440 | GL_RED_BIAS = 0x0D15, 441 | GL_GREEN_SCALE = 0x0D18, 442 | GL_GREEN_BIAS = 0x0D19, 443 | GL_BLUE_SCALE = 0x0D1A, 444 | GL_BLUE_BIAS = 0x0D1B, 445 | GL_ALPHA_SCALE = 0x0D1C, 446 | GL_ALPHA_BIAS = 0x0D1D, 447 | GL_DEPTH_SCALE = 0x0D1E, 448 | GL_DEPTH_BIAS = 0x0D1F, 449 | GL_PIXEL_MAP_S_TO_S_SIZE = 0x0CB1, 450 | GL_PIXEL_MAP_I_TO_I_SIZE = 0x0CB0, 451 | GL_PIXEL_MAP_I_TO_R_SIZE = 0x0CB2, 452 | GL_PIXEL_MAP_I_TO_G_SIZE = 0x0CB3, 453 | GL_PIXEL_MAP_I_TO_B_SIZE = 0x0CB4, 454 | GL_PIXEL_MAP_I_TO_A_SIZE = 0x0CB5, 455 | GL_PIXEL_MAP_R_TO_R_SIZE = 0x0CB6, 456 | GL_PIXEL_MAP_G_TO_G_SIZE = 0x0CB7, 457 | GL_PIXEL_MAP_B_TO_B_SIZE = 0x0CB8, 458 | GL_PIXEL_MAP_A_TO_A_SIZE = 0x0CB9, 459 | GL_PIXEL_MAP_S_TO_S = 0x0C71, 460 | GL_PIXEL_MAP_I_TO_I = 0x0C70, 461 | GL_PIXEL_MAP_I_TO_R = 0x0C72, 462 | GL_PIXEL_MAP_I_TO_G = 0x0C73, 463 | GL_PIXEL_MAP_I_TO_B = 0x0C74, 464 | GL_PIXEL_MAP_I_TO_A = 0x0C75, 465 | GL_PIXEL_MAP_R_TO_R = 0x0C76, 466 | GL_PIXEL_MAP_G_TO_G = 0x0C77, 467 | GL_PIXEL_MAP_B_TO_B = 0x0C78, 468 | GL_PIXEL_MAP_A_TO_A = 0x0C79, 469 | GL_PACK_ALIGNMENT = 0x0D05, 470 | GL_PACK_LSB_FIRST = 0x0D01, 471 | GL_PACK_ROW_LENGTH = 0x0D02, 472 | GL_PACK_SKIP_PIXELS = 0x0D04, 473 | GL_PACK_SKIP_ROWS = 0x0D03, 474 | GL_PACK_SWAP_BYTES = 0x0D00, 475 | GL_UNPACK_ALIGNMENT = 0x0CF5, 476 | GL_UNPACK_LSB_FIRST = 0x0CF1, 477 | GL_UNPACK_ROW_LENGTH = 0x0CF2, 478 | GL_UNPACK_SKIP_PIXELS = 0x0CF4, 479 | GL_UNPACK_SKIP_ROWS = 0x0CF3, 480 | GL_UNPACK_SWAP_BYTES = 0x0CF0, 481 | GL_ZOOM_X = 0x0D16, 482 | GL_ZOOM_Y = 0x0D17, 483 | 484 | /* Texture mapping */ 485 | GL_TEXTURE_ENV = 0x2300, 486 | GL_TEXTURE_ENV_MODE = 0x2200, 487 | GL_TEXTURE_1D = 0x0DE0, 488 | GL_TEXTURE_2D = 0x0DE1, 489 | GL_TEXTURE_WRAP_S = 0x2802, 490 | GL_TEXTURE_WRAP_T = 0x2803, 491 | GL_TEXTURE_MAG_FILTER = 0x2800, 492 | GL_TEXTURE_MIN_FILTER = 0x2801, 493 | GL_TEXTURE_ENV_COLOR = 0x2201, 494 | GL_TEXTURE_GEN_S = 0x0C60, 495 | GL_TEXTURE_GEN_T = 0x0C61, 496 | GL_TEXTURE_GEN_MODE = 0x2500, 497 | GL_TEXTURE_BORDER_COLOR = 0x1004, 498 | GL_TEXTURE_WIDTH = 0x1000, 499 | GL_TEXTURE_HEIGHT = 0x1001, 500 | GL_TEXTURE_BORDER = 0x1005, 501 | GL_TEXTURE_COMPONENTS = 0x1003, 502 | GL_NEAREST_MIPMAP_NEAREST = 0x2700, 503 | GL_NEAREST_MIPMAP_LINEAR = 0x2702, 504 | GL_LINEAR_MIPMAP_NEAREST = 0x2701, 505 | GL_LINEAR_MIPMAP_LINEAR = 0x2703, 506 | GL_OBJECT_LINEAR = 0x2401, 507 | GL_OBJECT_PLANE = 0x2501, 508 | GL_EYE_LINEAR = 0x2400, 509 | GL_EYE_PLANE = 0x2502, 510 | GL_SPHERE_MAP = 0x2402, 511 | GL_DECAL = 0x2101, 512 | GL_MODULATE = 0x2100, 513 | GL_NEAREST = 0x2600, 514 | GL_REPEAT = 0x2901, 515 | GL_CLAMP = 0x2900, 516 | GL_S = 0x2000, 517 | GL_T = 0x2001, 518 | GL_R = 0x2002, 519 | GL_Q = 0x2003, 520 | GL_TEXTURE_GEN_R = 0x0C62, 521 | GL_TEXTURE_GEN_Q = 0x0C63, 522 | 523 | GL_PROXY_TEXTURE_1D = 0x8063, 524 | GL_PROXY_TEXTURE_2D = 0x8064, 525 | GL_TEXTURE_PRIORITY = 0x8066, 526 | GL_TEXTURE_RESIDENT = 0x8067, 527 | GL_TEXTURE_1D_BINDING = 0x8068, 528 | GL_TEXTURE_2D_BINDING = 0x8069, 529 | 530 | /* Internal texture formats */ 531 | GL_ALPHA4 = 0x803B, 532 | GL_ALPHA8 = 0x803C, 533 | GL_ALPHA12 = 0x803D, 534 | GL_ALPHA16 = 0x803E, 535 | GL_LUMINANCE4 = 0x803F, 536 | GL_LUMINANCE8 = 0x8040, 537 | GL_LUMINANCE12 = 0x8041, 538 | GL_LUMINANCE16 = 0x8042, 539 | GL_LUMINANCE4_ALPHA4 = 0x8043, 540 | GL_LUMINANCE6_ALPHA2 = 0x8044, 541 | GL_LUMINANCE8_ALPHA8 = 0x8045, 542 | GL_LUMINANCE12_ALPHA4 = 0x8046, 543 | GL_LUMINANCE12_ALPHA12 = 0x8047, 544 | GL_LUMINANCE16_ALPHA16 = 0x8048, 545 | GL_INTENSITY = 0x8049, 546 | GL_INTENSITY4 = 0x804A, 547 | GL_INTENSITY8 = 0x804B, 548 | GL_INTENSITY12 = 0x804C, 549 | GL_INTENSITY16 = 0x804D, 550 | GL_R3_G3_B2 = 0x2A10, 551 | GL_RGB4 = 0x804F, 552 | GL_RGB5 = 0x8050, 553 | GL_RGB8 = 0x8051, 554 | GL_RGB10 = 0x8052, 555 | GL_RGB12 = 0x8053, 556 | GL_RGB16 = 0x8054, 557 | GL_RGBA2 = 0x8055, 558 | GL_RGBA4 = 0x8056, 559 | GL_RGB5_A1 = 0x8057, 560 | GL_RGBA8 = 0x8058, 561 | GL_RGB10_A2 = 0x8059, 562 | GL_RGBA12 = 0x805A, 563 | GL_RGBA16 = 0x805B, 564 | 565 | /* Utility */ 566 | GL_VENDOR = 0x1F00, 567 | GL_RENDERER = 0x1F01, 568 | GL_VERSION = 0x1F02, 569 | GL_EXTENSIONS = 0x1F03, 570 | 571 | /* Errors */ 572 | GL_INVALID_VALUE = 0x0501, 573 | GL_INVALID_ENUM = 0x0500, 574 | GL_INVALID_OPERATION = 0x0502, 575 | GL_STACK_OVERFLOW = 0x0503, 576 | GL_STACK_UNDERFLOW = 0x0504, 577 | GL_OUT_OF_MEMORY = 0x0505, 578 | 579 | /* 580 | * 1.0 Extensions 581 | */ 582 | /* GL_EXT_blend_minmax and GL_EXT_blend_color */ 583 | GL_CONSTANT_COLOR_EXT = 0x8001, 584 | GL_ONE_MINUS_CONSTANT_COLOR_EXT = 0x8002, 585 | GL_CONSTANT_ALPHA_EXT = 0x8003, 586 | GL_ONE_MINUS_CONSTANT_ALPHA_EXT = 0x8004, 587 | GL_BLEND_EQUATION_EXT = 0x8009, 588 | GL_MIN_EXT = 0x8007, 589 | GL_MAX_EXT = 0x8008, 590 | GL_FUNC_ADD_EXT = 0x8006, 591 | GL_FUNC_SUBTRACT_EXT = 0x800A, 592 | GL_FUNC_REVERSE_SUBTRACT_EXT = 0x800B, 593 | GL_BLEND_COLOR_EXT = 0x8005, 594 | 595 | /* GL_EXT_polygon_offset */ 596 | GL_POLYGON_OFFSET_EXT = 0x8037, 597 | GL_POLYGON_OFFSET_FACTOR_EXT = 0x8038, 598 | GL_POLYGON_OFFSET_BIAS_EXT = 0x8039, 599 | 600 | /* GL_EXT_vertex_array */ 601 | GL_VERTEX_ARRAY_EXT = 0x8074, 602 | GL_NORMAL_ARRAY_EXT = 0x8075, 603 | GL_COLOR_ARRAY_EXT = 0x8076, 604 | GL_INDEX_ARRAY_EXT = 0x8077, 605 | GL_TEXTURE_COORD_ARRAY_EXT = 0x8078, 606 | GL_EDGE_FLAG_ARRAY_EXT = 0x8079, 607 | GL_VERTEX_ARRAY_SIZE_EXT = 0x807A, 608 | GL_VERTEX_ARRAY_TYPE_EXT = 0x807B, 609 | GL_VERTEX_ARRAY_STRIDE_EXT = 0x807C, 610 | GL_VERTEX_ARRAY_COUNT_EXT = 0x807D, 611 | GL_NORMAL_ARRAY_TYPE_EXT = 0x807E, 612 | GL_NORMAL_ARRAY_STRIDE_EXT = 0x807F, 613 | GL_NORMAL_ARRAY_COUNT_EXT = 0x8080, 614 | GL_COLOR_ARRAY_SIZE_EXT = 0x8081, 615 | GL_COLOR_ARRAY_TYPE_EXT = 0x8082, 616 | GL_COLOR_ARRAY_STRIDE_EXT = 0x8083, 617 | GL_COLOR_ARRAY_COUNT_EXT = 0x8084, 618 | GL_INDEX_ARRAY_TYPE_EXT = 0x8085, 619 | GL_INDEX_ARRAY_STRIDE_EXT = 0x8086, 620 | GL_INDEX_ARRAY_COUNT_EXT = 0x8087, 621 | GL_TEXTURE_COORD_ARRAY_SIZE_EXT = 0x8088, 622 | GL_TEXTURE_COORD_ARRAY_TYPE_EXT = 0x8089, 623 | GL_TEXTURE_COORD_ARRAY_STRIDE_EXT= 0x808A, 624 | GL_TEXTURE_COORD_ARRAY_COUNT_EXT= 0x808B, 625 | GL_EDGE_FLAG_ARRAY_STRIDE_EXT = 0x808C, 626 | GL_EDGE_FLAG_ARRAY_COUNT_EXT = 0x808D, 627 | GL_VERTEX_ARRAY_POINTER_EXT = 0x808E, 628 | GL_NORMAL_ARRAY_POINTER_EXT = 0x808F, 629 | GL_COLOR_ARRAY_POINTER_EXT = 0x8090, 630 | GL_INDEX_ARRAY_POINTER_EXT = 0x8091, 631 | GL_TEXTURE_COORD_ARRAY_POINTER_EXT= 0x8092, 632 | GL_EDGE_FLAG_ARRAY_POINTER_EXT = 0x8093 633 | 634 | }; 635 | 636 | enum { 637 | GL_CURRENT_BIT = 0x00000001, 638 | GL_POINT_BIT = 0x00000002, 639 | GL_LINE_BIT = 0x00000004, 640 | GL_POLYGON_BIT = 0x00000008, 641 | GL_POLYGON_STIPPLE_BIT = 0x00000010, 642 | GL_PIXEL_MODE_BIT = 0x00000020, 643 | GL_LIGHTING_BIT = 0x00000040, 644 | GL_FOG_BIT = 0x00000080, 645 | GL_DEPTH_BUFFER_BIT = 0x00000100, 646 | GL_ACCUM_BUFFER_BIT = 0x00000200, 647 | GL_STENCIL_BUFFER_BIT = 0x00000400, 648 | GL_VIEWPORT_BIT = 0x00000800, 649 | GL_TRANSFORM_BIT = 0x00001000, 650 | GL_ENABLE_BIT = 0x00002000, 651 | GL_COLOR_BUFFER_BIT = 0x00004000, 652 | GL_HINT_BIT = 0x00008000, 653 | GL_EVAL_BIT = 0x00010000, 654 | GL_LIST_BIT = 0x00020000, 655 | GL_TEXTURE_BIT = 0x00040000, 656 | GL_SCISSOR_BIT = 0x00080000, 657 | GL_ALL_ATTRIB_BITS = 0x000fffff 658 | }; 659 | 660 | /* some types */ 661 | 662 | typedef int GLenum; 663 | typedef void GLvoid; 664 | typedef unsigned char GLboolean; 665 | typedef signed char GLbyte; /* 1-byte signed */ 666 | typedef short GLshort; /* 2-byte signed */ 667 | typedef int GLint; /* 4-byte signed */ 668 | typedef unsigned char GLubyte; /* 1-byte unsigned */ 669 | typedef unsigned short GLushort; /* 2-byte unsigned */ 670 | typedef unsigned int GLuint; /* 4-byte unsigned */ 671 | typedef float GLfloat; /* single precision float */ 672 | typedef double GLdouble; /* double precision float */ 673 | typedef int GLsizei; 674 | 675 | /* functions */ 676 | 677 | void glEnable(int code); 678 | void glDisable(int code); 679 | 680 | void glShadeModel(int mode); 681 | void glCullFace(int mode); 682 | void glPolygonMode(int face,int mode); 683 | 684 | void glBegin(int type); 685 | void glEnd(void); 686 | 687 | #define PROTO_GL1(name) \ 688 | void gl ## name ## 1f(float); \ 689 | void gl ## name ## 1d(double); \ 690 | void gl ## name ## 1fv(float *); \ 691 | void gl ## name ## 1dv(double *); 692 | 693 | #define PROTO_GL2(name) \ 694 | void gl ## name ## 2f(float ,float); \ 695 | void gl ## name ## 2d(double ,double); \ 696 | void gl ## name ## 2fv(float *); \ 697 | void gl ## name ## 2dv(double *); 698 | 699 | #define PROTO_GL3(name) \ 700 | void gl ## name ## 3f(float ,float ,float); \ 701 | void gl ## name ## 3d(double ,double ,double); \ 702 | void gl ## name ## 3fv(float *); \ 703 | void gl ## name ## 3dv(double *); 704 | 705 | #define PROTO_GL4(name) \ 706 | void gl ## name ## 4f(float ,float ,float, float ); \ 707 | void gl ## name ## 4d(double ,double ,double, double ); \ 708 | void gl ## name ## 4fv(float *); \ 709 | void gl ## name ## 4dv(double *); 710 | 711 | PROTO_GL2(Vertex) 712 | PROTO_GL3(Vertex) 713 | PROTO_GL4(Vertex) 714 | 715 | PROTO_GL3(Color) 716 | PROTO_GL4(Color) 717 | 718 | PROTO_GL3(Normal) 719 | 720 | PROTO_GL1(TexCoord) 721 | PROTO_GL2(TexCoord) 722 | PROTO_GL3(TexCoord) 723 | PROTO_GL4(TexCoord) 724 | 725 | void glEdgeFlag(int flag); 726 | 727 | /* matrix */ 728 | void glMatrixMode(int mode); 729 | void glLoadMatrixf(const float *m); 730 | void glLoadIdentity(void); 731 | void glMultMatrixf(const float *m); 732 | void glPushMatrix(void); 733 | void glPopMatrix(void); 734 | void glRotatef(float angle,float x,float y,float z); 735 | void glTranslatef(float x,float y,float z); 736 | void glScalef(float x,float y,float z); 737 | 738 | void glViewport(int x,int y,int width,int height); 739 | void glFrustum(double left,double right,double bottom,double top, 740 | double near,double far); 741 | 742 | /* lists */ 743 | unsigned int glGenLists(int range); 744 | int glIsList(unsigned int list); 745 | void glNewList(unsigned int list,int mode); 746 | void glEndList(void); 747 | void glCallList(unsigned int list); 748 | 749 | /* clear */ 750 | void glClear(int mask); 751 | void glClearColor(float r,float g,float b,float a); 752 | void glClearDepth(double depth); 753 | 754 | /* selection */ 755 | int glRenderMode(int mode); 756 | void glSelectBuffer(int size,unsigned int *buf); 757 | 758 | void glInitNames(void); 759 | void glPushName(unsigned int name); 760 | void glPopName(void); 761 | void glLoadName(unsigned int name); 762 | 763 | /* textures */ 764 | void glGenTextures(int n, unsigned int *textures); 765 | void glDeleteTextures(int n, const unsigned int *textures); 766 | void glBindTexture(int target,int texture); 767 | void glTexImage2D( int target, int level, int components, 768 | int width, int height, int border, 769 | int format, int type, void *pixels); 770 | void glTexEnvi(int target,int pname,int param); 771 | void glTexParameteri(int target,int pname,int param); 772 | void glPixelStorei(int pname,int param); 773 | 774 | /* lighting */ 775 | 776 | void glMaterialfv(int mode,int type,float *v); 777 | void glMaterialf(int mode,int type,float v); 778 | void glColorMaterial(int mode,int type); 779 | 780 | void glLightfv(int light,int type,float *v); 781 | void glLightf(int light,int type,float v); 782 | void glLightModeli(int pname,int param); 783 | void glLightModelfv(int pname,float *param); 784 | 785 | /* misc */ 786 | 787 | void glFlush(void); 788 | void glHint(int target,int mode); 789 | void glGetIntegerv(int pname,int *params); 790 | void glGetFloatv(int pname, float *v); 791 | void glFrontFace(int mode); 792 | 793 | /* opengl 1.2 arrays */ 794 | void glEnableClientState(GLenum array); 795 | void glDisableClientState(GLenum array); 796 | void glArrayElement(GLint i); 797 | void glVertexPointer(GLint size, GLenum type, GLsizei stride, 798 | const GLvoid *pointer); 799 | void glColorPointer(GLint size, GLenum type, GLsizei stride, 800 | const GLvoid *pointer); 801 | void glNormalPointer(GLenum type, GLsizei stride, 802 | const GLvoid *pointer); 803 | void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, 804 | const GLvoid *pointer); 805 | 806 | /* opengl 1.2 polygon offset */ 807 | void glPolygonOffset(GLfloat factor, GLfloat units); 808 | 809 | /* not implemented, just added to compile */ 810 | /* 811 | inline void glPointSize(float) {} 812 | inline void glLineWidth(float) {} 813 | inline void glDeleteLists(int, int) {} 814 | inline void glDepthFunc(int) {} 815 | inline void glBlendFunc(int, int) {} 816 | inline void glTexEnvf(int, int, int) {} 817 | inline void glOrtho(float,float,float,float,float,float){} 818 | inline void glVertex2i(int,int) {} 819 | inline void glDepthMask(int) {} 820 | inline void glFogi(int, int) {} 821 | inline void glFogfv(int, const float*) {} 822 | inline void glFogf(int, float) {} 823 | inline void glRasterPos2f(float, float) {} 824 | inline void glPolygonStipple(void*) {} 825 | inline void glTexParameterf(int, int, int) {}; 826 | */ 827 | /* non compatible functions */ 828 | 829 | void glDebug(int mode); 830 | 831 | void glInit(void *zbuffer); 832 | void glClose(void); 833 | 834 | #ifdef __cplusplus 835 | } 836 | #endif 837 | 838 | #endif 839 | -------------------------------------------------------------------------------- /include/GL/glu.h: -------------------------------------------------------------------------------- 1 | 2 | void gluPerspective( GLdouble fovy, GLdouble aspect, 3 | GLdouble zNear, GLdouble zFar ); 4 | 5 | typedef struct { 6 | int draw_style; 7 | } GLUquadricObj; 8 | 9 | #define GLU_LINE 0 10 | 11 | GLUquadricObj *gluNewQuadric(void); 12 | void gluQuadricDrawStyle(GLUquadricObj *obj, int style); 13 | 14 | void gluSphere(GLUquadricObj *qobj, 15 | float radius,int slices,int stacks); 16 | void gluCylinder( GLUquadricObj *qobj, 17 | GLdouble baseRadius, GLdouble topRadius, GLdouble height, 18 | GLint slices, GLint stacks ); 19 | void gluDisk( GLUquadricObj *qobj, 20 | GLdouble innerRadius, GLdouble outerRadius, 21 | GLint slices, GLint loops ); 22 | 23 | void drawTorus(float rc, int numc, float rt, int numt); 24 | -------------------------------------------------------------------------------- /include/zbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef _tgl_zbuffer_h_ 2 | #define _tgl_zbuffer_h_ 3 | 4 | /* 5 | * Z buffer 6 | */ 7 | 8 | #include "zfeatures.h" 9 | 10 | #define ZB_Z_BITS 16 11 | 12 | #define ZB_POINT_Z_FRAC_BITS 14 13 | 14 | #define ZB_POINT_S_MIN ( (1<<13) ) 15 | #define ZB_POINT_S_MAX ( (1<<22)-(1<<13) ) 16 | #define ZB_POINT_T_MIN ( (1<<21) ) 17 | #define ZB_POINT_T_MAX ( (1<<30)-(1<<21) ) 18 | 19 | #define ZB_POINT_RED_MIN ( (1<<10) ) 20 | #define ZB_POINT_RED_MAX ( (1<<16)-(1<<10) ) 21 | #define ZB_POINT_GREEN_MIN ( (1<<9) ) 22 | #define ZB_POINT_GREEN_MAX ( (1<<16)-(1<<9) ) 23 | #define ZB_POINT_BLUE_MIN ( (1<<10) ) 24 | #define ZB_POINT_BLUE_MAX ( (1<<16)-(1<<10) ) 25 | 26 | /* display modes */ 27 | #define ZB_MODE_5R6G5B 1 /* true color 16 bits */ 28 | #define ZB_MODE_INDEX 2 /* color index 8 bits */ 29 | #define ZB_MODE_RGBA 3 /* 32 bit rgba mode */ 30 | #define ZB_MODE_RGB24 4 /* 24 bit rgb mode */ 31 | #define ZB_NB_COLORS 225 /* number of colors for 8 bit display */ 32 | 33 | #if TGL_FEATURE_RENDER_BITS == 15 34 | 35 | #define RGB_TO_PIXEL(r,g,b) \ 36 | ((((r) >> 1) & 0x7c00) | (((g) >> 6) & 0x03e0) | ((b) >> 11)) 37 | typedef unsigned short PIXEL; 38 | /* bytes per pixel */ 39 | #define PSZB 2 40 | /* bits per pixel = (1 << PSZH) */ 41 | #define PSZSH 4 42 | 43 | #elif TGL_FEATURE_RENDER_BITS == 16 44 | 45 | /* 16 bit mode */ 46 | #define RGB_TO_PIXEL(r,g,b) \ 47 | (((r) & 0xF800) | (((g) >> 5) & 0x07E0) | ((b) >> 11)) 48 | typedef unsigned short PIXEL; 49 | #define PSZB 2 50 | #define PSZSH 4 51 | 52 | #elif TGL_FEATURE_RENDER_BITS == 24 53 | 54 | #define RGB_TO_PIXEL(r,g,b) \ 55 | ((((r) << 8) & 0xff0000) | ((g) & 0xff00) | ((b) >> 8)) 56 | typedef unsigned char PIXEL; 57 | #define PSZB 3 58 | #define PSZSH 5 59 | 60 | #elif TGL_FEATURE_RENDER_BITS == 32 61 | 62 | #define RGB_TO_PIXEL(r,g,b) \ 63 | ((((r) << 8) & 0xff0000) | ((g) & 0xff00) | ((b) >> 8)) 64 | typedef unsigned int PIXEL; 65 | #define PSZB 4 66 | #define PSZSH 5 67 | 68 | #else 69 | 70 | #error Incorrect number of bits per pixel 71 | 72 | #endif 73 | 74 | typedef struct { 75 | int xsize,ysize; 76 | int linesize; /* line size, in bytes */ 77 | int mode; 78 | 79 | unsigned short *zbuf; 80 | PIXEL *pbuf; 81 | int frame_buffer_allocated; 82 | 83 | int nb_colors; 84 | unsigned char *dctable; 85 | int *ctable; 86 | PIXEL *current_texture; 87 | } ZBuffer; 88 | 89 | typedef struct { 90 | int x,y,z; /* integer coordinates in the zbuffer */ 91 | int s,t; /* coordinates for the mapping */ 92 | int r,g,b; /* color indexes */ 93 | 94 | float sz,tz; /* temporary coordinates for mapping */ 95 | } ZBufferPoint; 96 | 97 | /* zbuffer.c */ 98 | 99 | ZBuffer *ZB_open(int xsize,int ysize,int mode, 100 | int nb_colors, 101 | unsigned char *color_indexes, 102 | int *color_table, 103 | void *frame_buffer); 104 | 105 | 106 | void ZB_close(ZBuffer *zb); 107 | 108 | void ZB_resize(ZBuffer *zb,void *frame_buffer,int xsize,int ysize); 109 | void ZB_clear(ZBuffer *zb,int clear_z,int z, 110 | int clear_color,int r,int g,int b); 111 | /* linesize is in BYTES */ 112 | void ZB_copyFrameBuffer(ZBuffer *zb,void *buf,int linesize); 113 | 114 | /* zdither.c */ 115 | 116 | void ZB_initDither(ZBuffer *zb,int nb_colors, 117 | unsigned char *color_indexes,int *color_table); 118 | void ZB_closeDither(ZBuffer *zb); 119 | void ZB_ditherFrameBuffer(ZBuffer *zb,unsigned char *dest, 120 | int linesize); 121 | 122 | /* zline.c */ 123 | 124 | void ZB_plot(ZBuffer *zb,ZBufferPoint *p); 125 | void ZB_line(ZBuffer *zb,ZBufferPoint *p1,ZBufferPoint *p2); 126 | void ZB_line_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2); 127 | 128 | /* ztriangle.c */ 129 | 130 | void ZB_setTexture(ZBuffer *zb, PIXEL *texture); 131 | 132 | void ZB_fillTriangleFlat(ZBuffer *zb, 133 | ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); 134 | 135 | void ZB_fillTriangleSmooth(ZBuffer *zb, 136 | ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); 137 | 138 | void ZB_fillTriangleMapping(ZBuffer *zb, 139 | ZBufferPoint *p1,ZBufferPoint *p2,ZBufferPoint *p3); 140 | 141 | void ZB_fillTriangleMappingPerspective(ZBuffer *zb, 142 | ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2); 143 | 144 | 145 | typedef void (*ZB_fillTriangleFunc)(ZBuffer *, 146 | ZBufferPoint *,ZBufferPoint *,ZBufferPoint *); 147 | 148 | /* memory.c */ 149 | void gl_free(void *p); 150 | void *gl_malloc(int size); 151 | void *gl_zalloc(int size); 152 | 153 | #endif /* _tgl_zbuffer_h_ */ 154 | -------------------------------------------------------------------------------- /include/zfeatures.h: -------------------------------------------------------------------------------- 1 | #ifndef _tgl_features_h_ 2 | #define _tgl_features_h_ 3 | 4 | /* Define BYTE_ORDER correctly where missing */ 5 | #ifndef BYTE_ORDER 6 | #define LITTLE_ENDIAN 1234 7 | #define BIG_ENDIAN 4321 8 | 9 | #if (defined(__i386__) || defined(__i386)) || \ 10 | defined(__ia64__) || defined(WIN32) || \ 11 | (defined(__alpha__) || defined(__alpha)) || \ 12 | defined(__arm__) || \ 13 | (defined(__mips__) && defined(__MIPSEL__)) || \ 14 | defined(__SYMBIAN32__) || \ 15 | defined(__x86_64__) || \ 16 | defined(__LITTLE_ENDIAN__) 17 | #define BYTE_ORDER LITTLE_ENDIAN 18 | #else 19 | #define BYTE_ORDER BIG_ENDIAN 20 | #endif 21 | 22 | #endif 23 | 24 | 25 | /* It is possible to enable/disable (compile time) features in this 26 | header file. */ 27 | 28 | #define TGL_FEATURE_ARRAYS 1 29 | #define TGL_FEATURE_DISPLAYLISTS 1 30 | #define TGL_FEATURE_POLYGON_OFFSET 1 31 | 32 | /* 33 | * Matrix of internal and external pixel formats supported. 'Y' means 34 | * supported. 35 | * 36 | * External 8 16 24 32 37 | * Internal 38 | * 15 . . . . 39 | * 16 Y Y Y Y 40 | * 24 . Y Y . 41 | * 32 . Y . Y 42 | * 43 | * 44 | * 15 bpp does not work yet (although it is easy to add it - ask me if 45 | * you need it). 46 | * 47 | * Internal pixel format: see TGL_FEATURE_RENDER_BITS 48 | * External pixel format: see TGL_FEATURE_xxx_BITS 49 | */ 50 | 51 | /* enable various convertion code from internal pixel format (usually 52 | 16 bits per pixel) to any external format */ 53 | #define TGL_FEATURE_16_BITS 1 54 | //#define TGL_FEATURE_8_BITS 1 55 | #define TGL_FEATURE_24_BITS 1 56 | #define TGL_FEATURE_32_BITS 1 57 | 58 | 59 | //#define TGL_FEATURE_RENDER_BITS 15 60 | #define TGL_FEATURE_RENDER_BITS 16 61 | //#define TGL_FEATURE_RENDER_BITS 24 62 | //#define TGL_FEATURE_RENDER_BITS 32 63 | 64 | #endif /* _tgl_features_h_ */ 65 | -------------------------------------------------------------------------------- /makeinclude: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | # C compiler 3 | 4 | # linux / Windows MinGW 5 | CC= gcc 6 | CFLAGS= -g -Wall -O2 -w 7 | LFLAGS= 8 | 9 | ##################################################################### 10 | # SDL configuration (for the examples only) 11 | 12 | UI_LIBS=$(shell sdl-config --libs) 13 | UI_INCLUDES=$(shell sdl-config --cflags) 14 | 15 | 16 | ##################################################################### 17 | # OpenGL configuration (for the examples only) 18 | 19 | # use TinySDGL 20 | GL_LIBS= -L../lib -lTinySDGL 21 | GL_INCLUDES= -I../include 22 | GL_DEPS= ../lib/libTinySDGL.a 23 | 24 | # use Mesa 25 | #GL_LIBS= -lMesaGL 26 | #GL_INCLUDES= 27 | #GL_DEPS= 28 | 29 | # use OpenGL 30 | #GL_LIBS= -lGL 31 | #GL_INCLUDES= 32 | #GL_DEPS= 33 | 34 | #################################################################### 35 | # Compile and link control 36 | 37 | DIRS= src examples 38 | 39 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(TinySDGL api arrays clear clip error get glu image_util init light list matrix memory misc msghandling oscontext select specbuf texture vertex zbuffer zdither zline zmath ztriangle) 2 | 3 | add_library(TinySDGL_shared SHARED api arrays clear clip error get glu image_util init light list matrix memory misc msghandling oscontext select specbuf texture vertex zbuffer zdither zline zmath ztriangle) 4 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | include ../makeinclude 2 | 3 | OBJS= api.o list.o vertex.o init.o matrix.o texture.o \ 4 | misc.o clear.o light.o clip.o select.o get.o error.o \ 5 | zbuffer.o zline.o zdither.o ztriangle.o \ 6 | zmath.o image_util.o oscontext.o msghandling.o \ 7 | arrays.o specbuf.o memory.o 8 | 9 | INCLUDES = -I../include 10 | LIB = libTinySDGL.a 11 | 12 | all: $(LIB) libTinyGLU.a 13 | 14 | $(LIB): $(OBJS) 15 | rm -f $(LIB) 16 | ar rcs $(LIB) $(OBJS) 17 | mv $(LIB) ../lib 18 | 19 | libTinyGLU.a: glu.o 20 | rm -f $@ 21 | ar rcs $@ $< 22 | mv $@ ../lib 23 | 24 | clean: 25 | rm -f *~ *.o *.a 26 | 27 | .c.o: 28 | $(CC) $(CFLAGS) $(INCLUDES) -c $*.c 29 | 30 | clip.o: zgl.h ../include/zfeatures.h 31 | vertex.o: zgl.h ../include/zfeatures.h 32 | light.o: zgl.h ../include/zfeatures.h 33 | matrix.o: zgl.h ../include/zfeatures.h 34 | list.o: zgl.h opinfo.h ../include/zfeatures.h 35 | arrays.c: zgl.h ../include/zfeatures.h 36 | specbuf.o: zgl.h ../include/zfeatures.h 37 | zline.o: zgl.h ../include/zfeatures.h zline.h 38 | glu.o: glu.c 39 | 40 | ztriangle.o: ztriangle.c ztriangle.h zgl.h ../include/zfeatures.h 41 | $(CC) $(CFLAGS) -Wno-uninitialized $(INCLUDES) -c $*.c 42 | -------------------------------------------------------------------------------- /src/api.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | #include 3 | /* glVertex */ 4 | 5 | void glVertex4f(float x,float y,float z,float w) 6 | { 7 | GLParam p[5]; 8 | 9 | p[0].op=OP_Vertex; 10 | p[1].f=x; 11 | p[2].f=y; 12 | p[3].f=z; 13 | p[4].f=w; 14 | 15 | gl_add_op(p); 16 | } 17 | 18 | void glVertex2f(float x,float y) 19 | { 20 | glVertex4f(x,y,0,1); 21 | } 22 | 23 | void glVertex3f(float x,float y,float z) 24 | { 25 | glVertex4f(x,y,z,1); 26 | } 27 | 28 | void glVertex3fv(float *v) 29 | { 30 | glVertex4f(v[0],v[1],v[2],1); 31 | } 32 | 33 | /* glNormal */ 34 | 35 | void glNormal3f(float x,float y,float z) 36 | { 37 | GLParam p[4]; 38 | 39 | p[0].op=OP_Normal; 40 | p[1].f=x; 41 | p[2].f=y; 42 | p[3].f=z; 43 | 44 | gl_add_op(p); 45 | } 46 | 47 | void glNormal3fv(float *v) 48 | { 49 | glNormal3f(v[0],v[1],v[2]); 50 | } 51 | 52 | /* glColor */ 53 | 54 | void glColor4f(float r,float g,float b,float a) 55 | { 56 | GLParam p[8]; 57 | 58 | p[0].op=OP_Color; 59 | p[1].f=r; 60 | p[2].f=g; 61 | p[3].f=b; 62 | p[4].f=a; 63 | /* direct convertion to integer to go faster if no shading */ 64 | p[5].ui = (unsigned int) (r * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) + 65 | ZB_POINT_RED_MIN); 66 | p[6].ui = (unsigned int) (g * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) + 67 | ZB_POINT_GREEN_MIN); 68 | p[7].ui = (unsigned int) (b * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) + 69 | ZB_POINT_BLUE_MIN); 70 | gl_add_op(p); 71 | } 72 | 73 | void glColor4fv(float *v) 74 | { 75 | GLParam p[8]; 76 | 77 | p[0].op=OP_Color; 78 | p[1].f=v[0]; 79 | p[2].f=v[1]; 80 | p[3].f=v[2]; 81 | p[4].f=v[3]; 82 | /* direct convertion to integer to go faster if no shading */ 83 | p[5].ui = (unsigned int) (v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) + 84 | ZB_POINT_RED_MIN); 85 | p[6].ui = (unsigned int) (v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) + 86 | ZB_POINT_GREEN_MIN); 87 | p[7].ui = (unsigned int) (v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) + 88 | ZB_POINT_BLUE_MIN); 89 | gl_add_op(p); 90 | } 91 | 92 | void glColor3f(float x,float y,float z) 93 | { 94 | //rev-color glColor4f(z,y,x,1); 95 | 96 | glColor4f(x,y,z,1); 97 | } 98 | 99 | void glColor3fv(float *v) 100 | { 101 | glColor4f(v[0],v[1],v[2],1); 102 | } 103 | 104 | 105 | /* TexCoord */ 106 | 107 | void glTexCoord4f(float s,float t,float r,float q) 108 | { 109 | GLParam p[5]; 110 | 111 | p[0].op=OP_TexCoord; 112 | p[1].f=s; 113 | p[2].f=t; 114 | p[3].f=r; 115 | p[4].f=q; 116 | 117 | gl_add_op(p); 118 | } 119 | 120 | void glTexCoord2f(float s,float t) 121 | { 122 | glTexCoord4f(s,t,0,1); 123 | } 124 | 125 | void glTexCoord2fv(float *v) 126 | { 127 | glTexCoord4f(v[0],v[1],0,1); 128 | } 129 | 130 | void glEdgeFlag(int flag) 131 | { 132 | GLParam p[2]; 133 | 134 | p[0].op=OP_EdgeFlag; 135 | p[1].i=flag; 136 | 137 | gl_add_op(p); 138 | } 139 | 140 | /* misc */ 141 | 142 | void glShadeModel(int mode) 143 | { 144 | GLParam p[2]; 145 | 146 | assert(mode == GL_FLAT || mode == GL_SMOOTH); 147 | 148 | p[0].op=OP_ShadeModel; 149 | p[1].i=mode; 150 | 151 | gl_add_op(p); 152 | } 153 | 154 | void glCullFace(int mode) 155 | { 156 | GLParam p[2]; 157 | 158 | assert(mode == GL_BACK || 159 | mode == GL_FRONT || 160 | mode == GL_FRONT_AND_BACK); 161 | 162 | p[0].op=OP_CullFace; 163 | p[1].i=mode; 164 | 165 | gl_add_op(p); 166 | } 167 | 168 | void glFrontFace(int mode) 169 | { 170 | GLParam p[2]; 171 | 172 | assert(mode == GL_CCW || mode == GL_CW); 173 | 174 | mode = (mode != GL_CCW); 175 | 176 | p[0].op=OP_FrontFace; 177 | p[1].i=mode; 178 | 179 | gl_add_op(p); 180 | } 181 | 182 | void glPolygonMode(int face,int mode) 183 | { 184 | GLParam p[3]; 185 | 186 | assert(face == GL_BACK || 187 | face == GL_FRONT || 188 | face == GL_FRONT_AND_BACK); 189 | assert(mode == GL_POINT || mode == GL_LINE || mode==GL_FILL); 190 | 191 | p[0].op=OP_PolygonMode; 192 | p[1].i=face; 193 | p[2].i=mode; 194 | 195 | gl_add_op(p); 196 | } 197 | 198 | 199 | /* glEnable / glDisable */ 200 | 201 | void glEnable(int cap) 202 | { 203 | GLParam p[3]; 204 | 205 | p[0].op=OP_EnableDisable; 206 | p[1].i=cap; 207 | p[2].i=1; 208 | 209 | gl_add_op(p); 210 | } 211 | 212 | void glDisable(int cap) 213 | { 214 | GLParam p[3]; 215 | 216 | p[0].op=OP_EnableDisable; 217 | p[1].i=cap; 218 | p[2].i=0; 219 | 220 | gl_add_op(p); 221 | } 222 | 223 | /* glBegin / glEnd */ 224 | 225 | void glBegin(int mode) 226 | { 227 | GLParam p[2]; 228 | 229 | p[0].op=OP_Begin; 230 | p[1].i=mode; 231 | 232 | gl_add_op(p); 233 | } 234 | 235 | void glEnd(void) 236 | { 237 | GLParam p[1]; 238 | 239 | p[0].op=OP_End; 240 | 241 | gl_add_op(p); 242 | } 243 | 244 | /* matrix */ 245 | 246 | void glMatrixMode(int mode) 247 | { 248 | GLParam p[2]; 249 | 250 | p[0].op=OP_MatrixMode; 251 | p[1].i=mode; 252 | 253 | gl_add_op(p); 254 | } 255 | 256 | void glLoadMatrixf(const float *m) 257 | { 258 | GLParam p[17]; 259 | int i; 260 | 261 | p[0].op=OP_LoadMatrix; 262 | for(i=0;i<16;i++) p[i+1].f=m[i]; 263 | 264 | gl_add_op(p); 265 | } 266 | 267 | void glLoadIdentity(void) 268 | { 269 | GLParam p[1]; 270 | 271 | p[0].op=OP_LoadIdentity; 272 | 273 | gl_add_op(p); 274 | } 275 | 276 | void glMultMatrixf(const float *m) 277 | { 278 | GLParam p[17]; 279 | int i; 280 | 281 | p[0].op=OP_MultMatrix; 282 | for(i=0;i<16;i++) p[i+1].f=m[i]; 283 | 284 | gl_add_op(p); 285 | } 286 | 287 | void glPushMatrix(void) 288 | { 289 | GLParam p[1]; 290 | 291 | p[0].op=OP_PushMatrix; 292 | 293 | gl_add_op(p); 294 | } 295 | 296 | void glPopMatrix(void) 297 | { 298 | GLParam p[1]; 299 | 300 | p[0].op=OP_PopMatrix; 301 | 302 | gl_add_op(p); 303 | } 304 | 305 | void glRotatef(float angle,float x,float y,float z) 306 | { 307 | GLParam p[5]; 308 | 309 | p[0].op=OP_Rotate; 310 | p[1].f=angle; 311 | p[2].f=x; 312 | p[3].f=y; 313 | p[4].f=z; 314 | 315 | gl_add_op(p); 316 | } 317 | 318 | void glTranslatef(float x,float y,float z) 319 | { 320 | GLParam p[4]; 321 | 322 | p[0].op=OP_Translate; 323 | p[1].f=x; 324 | p[2].f=y; 325 | p[3].f=z; 326 | 327 | gl_add_op(p); 328 | } 329 | 330 | void glScalef(float x,float y,float z) 331 | { 332 | GLParam p[4]; 333 | 334 | p[0].op=OP_Scale; 335 | p[1].f=x; 336 | p[2].f=y; 337 | p[3].f=z; 338 | 339 | gl_add_op(p); 340 | } 341 | 342 | 343 | void glViewport(int x,int y,int width,int height) 344 | { 345 | GLParam p[5]; 346 | 347 | p[0].op=OP_Viewport; 348 | p[1].i=x; 349 | p[2].i=y; 350 | p[3].i=width; 351 | p[4].i=height; 352 | 353 | gl_add_op(p); 354 | } 355 | 356 | void glFrustum(double left,double right,double bottom,double top, 357 | double near,double farv) 358 | { 359 | GLParam p[7]; 360 | 361 | p[0].op=OP_Frustum; 362 | p[1].f=left; 363 | p[2].f=right; 364 | p[3].f=bottom; 365 | p[4].f=top; 366 | p[5].f=near; 367 | p[6].f=farv; 368 | 369 | gl_add_op(p); 370 | } 371 | 372 | /* lightening */ 373 | 374 | void glMaterialfv(int mode,int type,float *v) 375 | { 376 | GLParam p[7]; 377 | int i,n; 378 | 379 | assert(mode == GL_FRONT || mode == GL_BACK || mode==GL_FRONT_AND_BACK); 380 | 381 | p[0].op=OP_Material; 382 | p[1].i=mode; 383 | p[2].i=type; 384 | n=4; 385 | if (type == GL_SHININESS) n=1; 386 | for(i=0;i<4;i++) p[3+i].f=v[i]; 387 | for(i=n;i<4;i++) p[3+i].f=0; 388 | 389 | gl_add_op(p); 390 | } 391 | 392 | void glMaterialf(int mode,int type,float v) 393 | { 394 | GLParam p[7]; 395 | int i; 396 | 397 | p[0].op=OP_Material; 398 | p[1].i=mode; 399 | p[2].i=type; 400 | p[3].f=v; 401 | for(i=0;i<3;i++) p[4+i].f=0; 402 | 403 | gl_add_op(p); 404 | } 405 | 406 | void glColorMaterial(int mode,int type) 407 | { 408 | GLParam p[3]; 409 | 410 | p[0].op=OP_ColorMaterial; 411 | p[1].i=mode; 412 | p[2].i=type; 413 | 414 | gl_add_op(p); 415 | } 416 | 417 | void glLightfv(int light,int type,float *v) 418 | { 419 | GLParam p[7]; 420 | int i; 421 | 422 | p[0].op=OP_Light; 423 | p[1].i=light; 424 | p[2].i=type; 425 | /* TODO: 3 composants ? */ 426 | for(i=0;i<4;i++) p[3+i].f=v[i]; 427 | 428 | gl_add_op(p); 429 | } 430 | 431 | 432 | void glLightf(int light,int type,float v) 433 | { 434 | GLParam p[7]; 435 | int i; 436 | 437 | p[0].op=OP_Light; 438 | p[1].i=light; 439 | p[2].i=type; 440 | p[3].f=v; 441 | for(i=0;i<3;i++) p[4+i].f=0; 442 | 443 | gl_add_op(p); 444 | } 445 | 446 | void glLightModeli(int pname,int param) 447 | { 448 | GLParam p[6]; 449 | int i; 450 | 451 | p[0].op=OP_LightModel; 452 | p[1].i=pname; 453 | p[2].f=(float)param; 454 | for(i=0;i<4;i++) p[3+i].f=0; 455 | 456 | gl_add_op(p); 457 | } 458 | 459 | void glLightModelfv(int pname,float *param) 460 | { 461 | GLParam p[6]; 462 | int i; 463 | 464 | p[0].op=OP_LightModel; 465 | p[1].i=pname; 466 | for(i=0;i<4;i++) p[2+i].f=param[i]; 467 | 468 | gl_add_op(p); 469 | } 470 | 471 | /* clear */ 472 | 473 | void glClear(int mask) 474 | { 475 | GLParam p[2]; 476 | 477 | p[0].op=OP_Clear; 478 | p[1].i=mask; 479 | 480 | gl_add_op(p); 481 | } 482 | 483 | void glClearColor(float r,float g,float b,float a) 484 | { 485 | GLParam p[5]; 486 | 487 | p[0].op=OP_ClearColor; 488 | p[1].f=r; 489 | p[2].f=g; 490 | p[3].f=b; 491 | p[4].f=a; 492 | 493 | gl_add_op(p); 494 | } 495 | 496 | void glClearDepth(double depth) 497 | { 498 | GLParam p[2]; 499 | 500 | p[0].op=OP_ClearDepth; 501 | p[1].f=depth; 502 | 503 | gl_add_op(p); 504 | } 505 | 506 | 507 | /* textures */ 508 | 509 | void glTexImage2D( int target, int level, int components, 510 | int width, int height, int border, 511 | int format, int type, void *pixels) 512 | { 513 | GLParam p[10]; 514 | 515 | p[0].op=OP_TexImage2D; 516 | p[1].i=target; 517 | p[2].i=level; 518 | p[3].i=components; 519 | p[4].i=width; 520 | p[5].i=height; 521 | p[6].i=border; 522 | p[7].i=format; 523 | p[8].i=type; 524 | p[9].p=pixels; 525 | 526 | gl_add_op(p); 527 | } 528 | 529 | 530 | void glBindTexture(int target,int texture) 531 | { 532 | GLParam p[3]; 533 | 534 | p[0].op=OP_BindTexture; 535 | p[1].i=target; 536 | p[2].i=texture; 537 | 538 | gl_add_op(p); 539 | } 540 | 541 | void glTexEnvi(int target,int pname,int param) 542 | { 543 | GLParam p[8]; 544 | 545 | p[0].op=OP_TexEnv; 546 | p[1].i=target; 547 | p[2].i=pname; 548 | p[3].i=param; 549 | p[4].f=0; 550 | p[5].f=0; 551 | p[6].f=0; 552 | p[7].f=0; 553 | 554 | gl_add_op(p); 555 | } 556 | 557 | void glTexParameteri(int target,int pname,int param) 558 | { 559 | GLParam p[8]; 560 | 561 | p[0].op=OP_TexParameter; 562 | p[1].i=target; 563 | p[2].i=pname; 564 | p[3].i=param; 565 | p[4].f=0; 566 | p[5].f=0; 567 | p[6].f=0; 568 | p[7].f=0; 569 | 570 | gl_add_op(p); 571 | } 572 | 573 | void glPixelStorei(int pname,int param) 574 | { 575 | GLParam p[3]; 576 | 577 | p[0].op=OP_PixelStore; 578 | p[1].i=pname; 579 | p[2].i=param; 580 | 581 | gl_add_op(p); 582 | } 583 | 584 | /* selection */ 585 | 586 | void glInitNames(void) 587 | { 588 | GLParam p[1]; 589 | 590 | p[0].op=OP_InitNames; 591 | 592 | gl_add_op(p); 593 | } 594 | 595 | void glPushName(unsigned int name) 596 | { 597 | GLParam p[2]; 598 | 599 | p[0].op=OP_PushName; 600 | p[1].i=name; 601 | 602 | gl_add_op(p); 603 | } 604 | 605 | void glPopName(void) 606 | { 607 | GLParam p[1]; 608 | 609 | p[0].op=OP_PopName; 610 | 611 | gl_add_op(p); 612 | } 613 | 614 | void glLoadName(unsigned int name) 615 | { 616 | GLParam p[2]; 617 | 618 | p[0].op=OP_LoadName; 619 | p[1].i=name; 620 | 621 | gl_add_op(p); 622 | } 623 | 624 | void 625 | glPolygonOffset(GLfloat factor, GLfloat units) 626 | { 627 | GLParam p[3]; 628 | p[0].op = OP_PolygonOffset; 629 | p[1].f = factor; 630 | p[2].f = units; 631 | } 632 | 633 | /* Special Functions */ 634 | 635 | void glCallList(unsigned int list) 636 | { 637 | GLParam p[2]; 638 | 639 | p[0].op=OP_CallList; 640 | p[1].i=list; 641 | 642 | gl_add_op(p); 643 | } 644 | 645 | void glFlush(void) 646 | { 647 | /* nothing to do */ 648 | } 649 | 650 | void glHint(int target,int mode) 651 | { 652 | GLParam p[3]; 653 | 654 | p[0].op=OP_Hint; 655 | p[1].i=target; 656 | p[2].i=mode; 657 | 658 | gl_add_op(p); 659 | } 660 | 661 | /* Non standard functions */ 662 | 663 | void glDebug(int mode) 664 | { 665 | GLContext *c=gl_get_context(); 666 | c->print_flag=mode; 667 | } 668 | 669 | -------------------------------------------------------------------------------- /src/arrays.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | #include 3 | #include 4 | 5 | #define VERTEX_ARRAY 0x0001 6 | #define COLOR_ARRAY 0x0002 7 | #define NORMAL_ARRAY 0x0004 8 | #define TEXCOORD_ARRAY 0x0008 9 | 10 | void 11 | glopArrayElement(GLContext *c, GLParam *param) 12 | { 13 | int i; 14 | int states = c->client_states; 15 | int idx = param[1].i; 16 | 17 | if (states & COLOR_ARRAY) { 18 | GLParam p[5]; 19 | int size = c->color_array_size; 20 | i = idx * (size + c->color_array_stride); 21 | p[1].f = c->color_array[i]; 22 | p[2].f = c->color_array[i+1]; 23 | p[3].f = c->color_array[i+2]; 24 | p[4].f = size > 3 ? c->color_array[i+3] : 1.0f; 25 | glopColor(c, p); 26 | } 27 | if (states & NORMAL_ARRAY) { 28 | i = idx * (3 + c->normal_array_stride); 29 | c->current_normal.X = c->normal_array[i]; 30 | c->current_normal.Y = c->normal_array[i+1]; 31 | c->current_normal.Z = c->normal_array[i+2]; 32 | c->current_normal.Z = 0.0f; 33 | } 34 | if (states & TEXCOORD_ARRAY) { 35 | int size = c->texcoord_array_size; 36 | i = idx * (size + c->texcoord_array_stride); 37 | c->current_tex_coord.X = c->texcoord_array[i]; 38 | c->current_tex_coord.Y = c->texcoord_array[i+1]; 39 | c->current_tex_coord.Z = size > 2 ? c->texcoord_array[i+2] : 0.0f; 40 | c->current_tex_coord.W = size > 3 ? c->texcoord_array[i+3] : 1.0f; 41 | } 42 | if (states & VERTEX_ARRAY) { 43 | GLParam p[5]; 44 | int size = c->vertex_array_size; 45 | i = idx * (size + c->vertex_array_stride); 46 | p[1].f = c->vertex_array[i]; 47 | p[2].f = c->vertex_array[i+1]; 48 | p[3].f = size > 2 ? c->vertex_array[i+2] : 0.0f; 49 | p[4].f = size > 3 ? c->vertex_array[i+3] : 1.0f; 50 | glopVertex(c, p); 51 | } 52 | } 53 | 54 | void 55 | glArrayElement(GLint i) 56 | { 57 | GLParam p[2]; 58 | p[0].op = OP_ArrayElement; 59 | p[1].i = i; 60 | gl_add_op(p); 61 | } 62 | 63 | 64 | void 65 | glopEnableClientState(GLContext *c, GLParam *p) 66 | { 67 | c->client_states |= p[1].i; 68 | } 69 | 70 | void 71 | glEnableClientState(GLenum array) 72 | { 73 | GLParam p[2]; 74 | p[0].op = OP_EnableClientState; 75 | 76 | switch(array) { 77 | case GL_VERTEX_ARRAY: 78 | p[1].i = VERTEX_ARRAY; 79 | break; 80 | case GL_NORMAL_ARRAY: 81 | p[1].i = NORMAL_ARRAY; 82 | break; 83 | case GL_COLOR_ARRAY: 84 | p[1].i = COLOR_ARRAY; 85 | break; 86 | case GL_TEXTURE_COORD_ARRAY: 87 | p[1].i = TEXCOORD_ARRAY; 88 | break; 89 | default: 90 | assert(0); 91 | break; 92 | } 93 | gl_add_op(p); 94 | } 95 | 96 | void 97 | glopDisableClientState(GLContext *c, GLParam *p) 98 | { 99 | c->client_states &= p[1].i; 100 | } 101 | 102 | void 103 | glDisableClientState(GLenum array) 104 | { 105 | GLParam p[2]; 106 | p[0].op = OP_DisableClientState; 107 | 108 | switch(array) { 109 | case GL_VERTEX_ARRAY: 110 | p[1].i = ~VERTEX_ARRAY; 111 | break; 112 | case GL_NORMAL_ARRAY: 113 | p[1].i = ~NORMAL_ARRAY; 114 | break; 115 | case GL_COLOR_ARRAY: 116 | p[1].i = ~COLOR_ARRAY; 117 | break; 118 | case GL_TEXTURE_COORD_ARRAY: 119 | p[1].i = ~TEXCOORD_ARRAY; 120 | break; 121 | default: 122 | assert(0); 123 | break; 124 | } 125 | gl_add_op(p); 126 | } 127 | 128 | void 129 | glopVertexPointer(GLContext *c, GLParam *p) 130 | { 131 | c->vertex_array_size = p[1].i; 132 | c->vertex_array_stride = p[2].i; 133 | c->vertex_array = p[3].p; 134 | } 135 | 136 | void 137 | glVertexPointer(GLint size, GLenum type, GLsizei stride, 138 | const GLvoid *pointer) 139 | { 140 | GLParam p[4]; 141 | assert(type == GL_FLOAT); 142 | p[0].op = OP_VertexPointer; 143 | p[1].i = size; 144 | p[2].i = stride; 145 | p[3].p = (void*)pointer; 146 | gl_add_op(p); 147 | } 148 | 149 | void 150 | glopColorPointer(GLContext *c, GLParam *p) 151 | { 152 | c->color_array_size = p[1].i; 153 | c->color_array_stride = p[2].i; 154 | c->color_array = p[3].p; 155 | } 156 | 157 | void 158 | glColorPointer(GLint size, GLenum type, GLsizei stride, 159 | const GLvoid *pointer) 160 | { 161 | GLParam p[4]; 162 | assert(type == GL_FLOAT); 163 | p[0].op = OP_ColorPointer; 164 | p[1].i = size; 165 | p[2].i = stride; 166 | p[3].p = (void*)pointer; 167 | gl_add_op(p); 168 | } 169 | 170 | void 171 | glopNormalPointer(GLContext *c, GLParam *p) 172 | { 173 | c->normal_array_stride = p[1].i; 174 | c->normal_array = p[2].p; 175 | } 176 | 177 | void 178 | glNormalPointer(GLenum type, GLsizei stride, 179 | const GLvoid *pointer) 180 | { 181 | GLParam p[3]; 182 | assert(type == GL_FLOAT); 183 | p[0].op = OP_NormalPointer; 184 | p[1].i = stride; 185 | p[2].p = (void*)pointer; 186 | } 187 | 188 | void 189 | glopTexCoordPointer(GLContext *c, GLParam *p) 190 | { 191 | c->texcoord_array_size = p[1].i; 192 | c->texcoord_array_stride = p[2].i; 193 | c->texcoord_array = p[3].p; 194 | } 195 | 196 | void 197 | glTexCoordPointer(GLint size, GLenum type, GLsizei stride, 198 | const GLvoid *pointer) 199 | { 200 | GLParam p[4]; 201 | assert(type == GL_FLOAT); 202 | p[0].op = OP_TexCoordPointer; 203 | p[1].i = size; 204 | p[2].i = stride; 205 | p[3].p = (void*)pointer; 206 | } 207 | -------------------------------------------------------------------------------- /src/clear.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | 4 | void glopClearColor(GLContext *c,GLParam *p) 5 | { 6 | c->clear_color.v[0]=p[1].f; 7 | c->clear_color.v[1]=p[2].f; 8 | c->clear_color.v[2]=p[3].f; 9 | c->clear_color.v[3]=p[4].f; 10 | } 11 | void glopClearDepth(GLContext *c,GLParam *p) 12 | { 13 | c->clear_depth=p[1].f; 14 | } 15 | 16 | 17 | void glopClear(GLContext *c,GLParam *p) 18 | { 19 | int mask=p[1].i; 20 | int z=0; 21 | int r=(int)(c->clear_color.v[0]*65535); 22 | int g=(int)(c->clear_color.v[1]*65535); 23 | int b=(int)(c->clear_color.v[2]*65535); 24 | 25 | /* TODO : correct value of Z */ 26 | 27 | ZB_clear(c->zb,mask & GL_DEPTH_BUFFER_BIT,z, 28 | mask & GL_COLOR_BUFFER_BIT,r,g,b); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/clip.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | /* fill triangle profile */ 4 | /* #define PROFILE */ 5 | 6 | #define CLIP_XMIN (1<<0) 7 | #define CLIP_XMAX (1<<1) 8 | #define CLIP_YMIN (1<<2) 9 | #define CLIP_YMAX (1<<3) 10 | #define CLIP_ZMIN (1<<4) 11 | #define CLIP_ZMAX (1<<5) 12 | 13 | void gl_transform_to_viewport(GLContext *c,GLVertex *v) 14 | { 15 | float winv; 16 | 17 | /* coordinates */ 18 | winv=1.0/v->pc.W; 19 | v->zp.x= (int) ( v->pc.X * winv * c->viewport.scale.X 20 | + c->viewport.trans.X ); 21 | v->zp.y= (int) ( v->pc.Y * winv * c->viewport.scale.Y 22 | + c->viewport.trans.Y ); 23 | v->zp.z= (int) ( v->pc.Z * winv * c->viewport.scale.Z 24 | + c->viewport.trans.Z ); 25 | /* color */ 26 | if (c->lighting_enabled) { 27 | v->zp.r=(int)(v->color.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) 28 | + ZB_POINT_RED_MIN); 29 | v->zp.g=(int)(v->color.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN) 30 | + ZB_POINT_GREEN_MIN); 31 | v->zp.b=(int)(v->color.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN) 32 | + ZB_POINT_BLUE_MIN); 33 | } else { 34 | /* no need to convert to integer if no lighting : take current color */ 35 | v->zp.r = c->longcurrent_color[0]; 36 | v->zp.g = c->longcurrent_color[1]; 37 | v->zp.b = c->longcurrent_color[2]; 38 | } 39 | 40 | /* texture */ 41 | 42 | if (c->texture_2d_enabled) { 43 | v->zp.s=(int)(v->tex_coord.X * (ZB_POINT_S_MAX - ZB_POINT_S_MIN) 44 | + ZB_POINT_S_MIN); 45 | v->zp.t=(int)(v->tex_coord.Y * (ZB_POINT_T_MAX - ZB_POINT_T_MIN) 46 | + ZB_POINT_T_MIN); 47 | } 48 | } 49 | 50 | 51 | static void gl_add_select1(GLContext *c,int z1,int z2,int z3) 52 | { 53 | unsigned int min,max; 54 | min=max=z1; 55 | if (z2max) max=z2; 58 | if (z3>max) max=z3; 59 | 60 | gl_add_select(c,0xffffffff-min,0xffffffff-max); 61 | } 62 | 63 | /* point */ 64 | 65 | void gl_draw_point(GLContext *c,GLVertex *p0) 66 | { 67 | if (p0->clip_code == 0) { 68 | if (c->render_mode == GL_SELECT) { 69 | gl_add_select(c,p0->zp.z,p0->zp.z); 70 | } else { 71 | ZB_plot(c->zb,&p0->zp); 72 | } 73 | } 74 | } 75 | 76 | /* line */ 77 | 78 | static inline void interpolate(GLVertex *q,GLVertex *p0,GLVertex *p1,float t) 79 | { 80 | q->pc.X=p0->pc.X+(p1->pc.X-p0->pc.X)*t; 81 | q->pc.Y=p0->pc.Y+(p1->pc.Y-p0->pc.Y)*t; 82 | q->pc.Z=p0->pc.Z+(p1->pc.Z-p0->pc.Z)*t; 83 | q->pc.W=p0->pc.W+(p1->pc.W-p0->pc.W)*t; 84 | 85 | q->color.v[0]=p0->color.v[0] + (p1->color.v[0]-p0->color.v[0])*t; 86 | q->color.v[1]=p0->color.v[1] + (p1->color.v[1]-p0->color.v[1])*t; 87 | q->color.v[2]=p0->color.v[2] + (p1->color.v[2]-p0->color.v[2])*t; 88 | } 89 | 90 | /* 91 | * Line Clipping 92 | */ 93 | 94 | /* Line Clipping algorithm from 'Computer Graphics', Principles and 95 | Practice */ 96 | static inline int ClipLine1(float denom,float num,float *tmin,float *tmax) 97 | { 98 | float t; 99 | 100 | if (denom>0) { 101 | t=num/denom; 102 | if (t>*tmax) return 0; 103 | if (t>*tmin) *tmin=t; 104 | } else if (denom<0) { 105 | t=num/denom; 106 | if (t<*tmin) return 0; 107 | if (t<*tmax) *tmax=t; 108 | } else if (num>0) return 0; 109 | return 1; 110 | } 111 | 112 | void gl_draw_line(GLContext *c,GLVertex *p1,GLVertex *p2) 113 | { 114 | float dx,dy,dz,dw,x1,y1,z1,w1; 115 | float tmin,tmax; 116 | GLVertex q1,q2; 117 | int cc1,cc2; 118 | 119 | cc1=p1->clip_code; 120 | cc2=p2->clip_code; 121 | 122 | if ( (cc1 | cc2) == 0) { 123 | if (c->render_mode == GL_SELECT) { 124 | gl_add_select1(c,p1->zp.z,p2->zp.z,p2->zp.z); 125 | } else { 126 | if (c->depth_test) 127 | ZB_line_z(c->zb,&p1->zp,&p2->zp); 128 | else 129 | ZB_line(c->zb,&p1->zp,&p2->zp); 130 | } 131 | } else if ( (cc1&cc2) != 0 ) { 132 | return; 133 | } else { 134 | dx=p2->pc.X-p1->pc.X; 135 | dy=p2->pc.Y-p1->pc.Y; 136 | dz=p2->pc.Z-p1->pc.Z; 137 | dw=p2->pc.W-p1->pc.W; 138 | x1=p1->pc.X; 139 | y1=p1->pc.Y; 140 | z1=p1->pc.Z; 141 | w1=p1->pc.W; 142 | 143 | tmin=0; 144 | tmax=1; 145 | if (ClipLine1(dx+dw,-x1-w1,&tmin,&tmax) && 146 | ClipLine1(-dx+dw,x1-w1,&tmin,&tmax) && 147 | ClipLine1(dy+dw,-y1-w1,&tmin,&tmax) && 148 | ClipLine1(-dy+dw,y1-w1,&tmin,&tmax) && 149 | ClipLine1(dz+dw,-z1-w1,&tmin,&tmax) && 150 | ClipLine1(-dz+dw,z1-w1,&tmin,&tmax)) { 151 | 152 | interpolate(&q1,p1,p2,tmin); 153 | interpolate(&q2,p1,p2,tmax); 154 | gl_transform_to_viewport(c,&q1); 155 | gl_transform_to_viewport(c,&q2); 156 | 157 | if (c->depth_test) 158 | ZB_line_z(c->zb,&q1.zp,&q2.zp); 159 | else 160 | ZB_line(c->zb,&q1.zp,&q2.zp); 161 | } 162 | } 163 | } 164 | 165 | 166 | /* triangle */ 167 | 168 | /* 169 | * Clipping 170 | */ 171 | 172 | /* We clip the segment [a,b] against the 6 planes of the normal volume. 173 | * We compute the point 'c' of intersection and the value of the parameter 't' 174 | * of the intersection if x=a+t(b-a). 175 | */ 176 | 177 | #define clip_func(name,sign,dir,dir1,dir2) \ 178 | static float name(V4 *c,V4 *a,V4 *b) \ 179 | {\ 180 | float t,dX,dY,dZ,dW,den;\ 181 | dX = (b->X - a->X);\ 182 | dY = (b->Y - a->Y);\ 183 | dZ = (b->Z - a->Z);\ 184 | dW = (b->W - a->W);\ 185 | den = -(sign d ## dir) + dW;\ 186 | if (den == 0) t=0;\ 187 | else t = ( sign a->dir - a->W) / den;\ 188 | c->dir1 = a->dir1 + t * d ## dir1;\ 189 | c->dir2 = a->dir2 + t * d ## dir2;\ 190 | c->W = a->W + t * dW;\ 191 | c->dir = sign c->W;\ 192 | return t;\ 193 | } 194 | 195 | 196 | clip_func(clip_xmin,-,X,Y,Z) 197 | 198 | clip_func(clip_xmax,+,X,Y,Z) 199 | 200 | clip_func(clip_ymin,-,Y,X,Z) 201 | 202 | clip_func(clip_ymax,+,Y,X,Z) 203 | 204 | clip_func(clip_zmin,-,Z,X,Y) 205 | 206 | clip_func(clip_zmax,+,Z,X,Y) 207 | 208 | 209 | float (*clip_proc[6])(V4 *,V4 *,V4 *)= { 210 | clip_xmin,clip_xmax, 211 | clip_ymin,clip_ymax, 212 | clip_zmin,clip_zmax 213 | }; 214 | 215 | static inline void updateTmp(GLContext *c, 216 | GLVertex *q,GLVertex *p0,GLVertex *p1,float t) 217 | { 218 | if (c->current_shade_model == GL_SMOOTH) { 219 | q->color.v[0]=p0->color.v[0] + (p1->color.v[0]-p0->color.v[0])*t; 220 | q->color.v[1]=p0->color.v[1] + (p1->color.v[1]-p0->color.v[1])*t; 221 | q->color.v[2]=p0->color.v[2] + (p1->color.v[2]-p0->color.v[2])*t; 222 | } else { 223 | q->color.v[0]=p0->color.v[0]; 224 | q->color.v[1]=p0->color.v[1]; 225 | q->color.v[2]=p0->color.v[2]; 226 | } 227 | 228 | if (c->texture_2d_enabled) { 229 | q->tex_coord.X=p0->tex_coord.X + (p1->tex_coord.X-p0->tex_coord.X)*t; 230 | q->tex_coord.Y=p0->tex_coord.Y + (p1->tex_coord.Y-p0->tex_coord.Y)*t; 231 | } 232 | 233 | q->clip_code=gl_clipcode(q->pc.X,q->pc.Y,q->pc.Z,q->pc.W); 234 | if (q->clip_code==0) 235 | gl_transform_to_viewport(c,q); 236 | } 237 | 238 | static void gl_draw_triangle_clip(GLContext *c, 239 | GLVertex *p0,GLVertex *p1,GLVertex *p2,int clip_bit); 240 | 241 | void gl_draw_triangle(GLContext *c, 242 | GLVertex *p0,GLVertex *p1,GLVertex *p2) 243 | { 244 | int co,c_and,cc[3],front; 245 | float norm; 246 | 247 | cc[0]=p0->clip_code; 248 | cc[1]=p1->clip_code; 249 | cc[2]=p2->clip_code; 250 | 251 | co=cc[0] | cc[1] | cc[2]; 252 | 253 | /* we handle the non clipped case here to go faster */ 254 | if (co==0) { 255 | 256 | norm=(float)(p1->zp.x-p0->zp.x)*(float)(p2->zp.y-p0->zp.y)- 257 | (float)(p2->zp.x-p0->zp.x)*(float)(p1->zp.y-p0->zp.y); 258 | 259 | if (norm == 0) return; 260 | 261 | front = norm < 0.0; 262 | front = front ^ c->current_front_face; 263 | 264 | /* back face culling */ 265 | if (c->cull_face_enabled) { 266 | /* most used case first */ 267 | if (c->current_cull_face == GL_BACK) { 268 | if (front == 0) return; 269 | c->draw_triangle_front(c,p0,p1,p2); 270 | } else if (c->current_cull_face == GL_FRONT) { 271 | if (front != 0) return; 272 | c->draw_triangle_back(c,p0,p1,p2); 273 | } else { 274 | return; 275 | } 276 | } else { 277 | /* no culling */ 278 | if (front) { 279 | c->draw_triangle_front(c,p0,p1,p2); 280 | } else { 281 | c->draw_triangle_back(c,p0,p1,p2); 282 | } 283 | } 284 | } else { 285 | c_and=cc[0] & cc[1] & cc[2]; 286 | if (c_and==0) { 287 | gl_draw_triangle_clip(c,p0,p1,p2,0); 288 | } 289 | } 290 | } 291 | 292 | static void gl_draw_triangle_clip(GLContext *c, 293 | GLVertex *p0,GLVertex *p1,GLVertex *p2,int clip_bit) 294 | { 295 | int co,c_and,co1,cc[3],edge_flag_tmp,clip_mask; 296 | GLVertex tmp1,tmp2,*q[3]; 297 | float tt; 298 | 299 | cc[0]=p0->clip_code; 300 | cc[1]=p1->clip_code; 301 | cc[2]=p2->clip_code; 302 | 303 | co=cc[0] | cc[1] | cc[2]; 304 | if (co == 0) { 305 | gl_draw_triangle(c,p0,p1,p2); 306 | } else { 307 | c_and=cc[0] & cc[1] & cc[2]; 308 | /* the triangle is completely outside */ 309 | if (c_and!=0) return; 310 | 311 | /* find the next direction to clip */ 312 | while (clip_bit < 6 && (co & (1 << clip_bit)) == 0) { 313 | clip_bit++; 314 | } 315 | 316 | /* this test can be true only in case of rounding errors */ 317 | if (clip_bit == 6) { 318 | #if 0 319 | printf("Error:\n"); 320 | printf("%f %f %f %f\n",p0->pc.X,p0->pc.Y,p0->pc.Z,p0->pc.W); 321 | printf("%f %f %f %f\n",p1->pc.X,p1->pc.Y,p1->pc.Z,p1->pc.W); 322 | printf("%f %f %f %f\n",p2->pc.X,p2->pc.Y,p2->pc.Z,p2->pc.W); 323 | #endif 324 | return; 325 | } 326 | 327 | clip_mask = 1 << clip_bit; 328 | co1=(cc[0] ^ cc[1] ^ cc[2]) & clip_mask; 329 | 330 | if (co1) { 331 | /* one point outside */ 332 | 333 | if (cc[0] & clip_mask) { q[0]=p0; q[1]=p1; q[2]=p2; } 334 | else if (cc[1] & clip_mask) { q[0]=p1; q[1]=p2; q[2]=p0; } 335 | else { q[0]=p2; q[1]=p0; q[2]=p1; } 336 | 337 | tt=clip_proc[clip_bit](&tmp1.pc,&q[0]->pc,&q[1]->pc); 338 | updateTmp(c,&tmp1,q[0],q[1],tt); 339 | 340 | tt=clip_proc[clip_bit](&tmp2.pc,&q[0]->pc,&q[2]->pc); 341 | updateTmp(c,&tmp2,q[0],q[2],tt); 342 | 343 | tmp1.edge_flag=q[0]->edge_flag; 344 | edge_flag_tmp=q[2]->edge_flag; 345 | q[2]->edge_flag=0; 346 | gl_draw_triangle_clip(c,&tmp1,q[1],q[2],clip_bit+1); 347 | 348 | tmp2.edge_flag=1; 349 | tmp1.edge_flag=0; 350 | q[2]->edge_flag=edge_flag_tmp; 351 | gl_draw_triangle_clip(c,&tmp2,&tmp1,q[2],clip_bit+1); 352 | } else { 353 | /* two points outside */ 354 | 355 | if ((cc[0] & clip_mask)==0) { q[0]=p0; q[1]=p1; q[2]=p2; } 356 | else if ((cc[1] & clip_mask)==0) { q[0]=p1; q[1]=p2; q[2]=p0; } 357 | else { q[0]=p2; q[1]=p0; q[2]=p1; } 358 | 359 | tt=clip_proc[clip_bit](&tmp1.pc,&q[0]->pc,&q[1]->pc); 360 | updateTmp(c,&tmp1,q[0],q[1],tt); 361 | 362 | tt=clip_proc[clip_bit](&tmp2.pc,&q[0]->pc,&q[2]->pc); 363 | updateTmp(c,&tmp2,q[0],q[2],tt); 364 | 365 | tmp1.edge_flag=1; 366 | tmp2.edge_flag=q[2]->edge_flag; 367 | gl_draw_triangle_clip(c,q[0],&tmp1,&tmp2,clip_bit+1); 368 | } 369 | } 370 | } 371 | 372 | 373 | void gl_draw_triangle_select(GLContext *c, 374 | GLVertex *p0,GLVertex *p1,GLVertex *p2) 375 | { 376 | gl_add_select1(c,p0->zp.z,p1->zp.z,p2->zp.z); 377 | } 378 | 379 | #ifdef PROFILE 380 | int count_triangles,count_triangles_textured,count_pixels; 381 | #endif 382 | 383 | void gl_draw_triangle_fill(GLContext *c, 384 | GLVertex *p0,GLVertex *p1,GLVertex *p2) 385 | { 386 | #ifdef PROFILE 387 | { 388 | int norm; 389 | assert(p0->zp.x >= 0 && p0->zp.x < c->zb->xsize); 390 | assert(p0->zp.y >= 0 && p0->zp.y < c->zb->ysize); 391 | assert(p1->zp.x >= 0 && p1->zp.x < c->zb->xsize); 392 | assert(p1->zp.y >= 0 && p1->zp.y < c->zb->ysize); 393 | assert(p2->zp.x >= 0 && p2->zp.x < c->zb->xsize); 394 | assert(p2->zp.y >= 0 && p2->zp.y < c->zb->ysize); 395 | 396 | norm=(p1->zp.x-p0->zp.x)*(p2->zp.y-p0->zp.y)- 397 | (p2->zp.x-p0->zp.x)*(p1->zp.y-p0->zp.y); 398 | count_pixels+=abs(norm)/2; 399 | count_triangles++; 400 | } 401 | #endif 402 | 403 | if (c->texture_2d_enabled) { 404 | #ifdef PROFILE 405 | count_triangles_textured++; 406 | #endif 407 | ZB_setTexture(c->zb,c->current_texture->images[0].pixmap); 408 | ZB_fillTriangleMappingPerspective(c->zb,&p0->zp,&p1->zp,&p2->zp); 409 | } else if (c->current_shade_model == GL_SMOOTH) { 410 | ZB_fillTriangleSmooth(c->zb,&p0->zp,&p1->zp,&p2->zp); 411 | } else { 412 | ZB_fillTriangleFlat(c->zb,&p0->zp,&p1->zp,&p2->zp); 413 | } 414 | } 415 | 416 | /* Render a clipped triangle in line mode */ 417 | 418 | void gl_draw_triangle_line(GLContext *c, 419 | GLVertex *p0,GLVertex *p1,GLVertex *p2) 420 | { 421 | if (c->depth_test) { 422 | if (p0->edge_flag) ZB_line_z(c->zb,&p0->zp,&p1->zp); 423 | if (p1->edge_flag) ZB_line_z(c->zb,&p1->zp,&p2->zp); 424 | if (p2->edge_flag) ZB_line_z(c->zb,&p2->zp,&p0->zp); 425 | } else { 426 | if (p0->edge_flag) ZB_line(c->zb,&p0->zp,&p1->zp); 427 | if (p1->edge_flag) ZB_line(c->zb,&p1->zp,&p2->zp); 428 | if (p2->edge_flag) ZB_line(c->zb,&p2->zp,&p0->zp); 429 | } 430 | } 431 | 432 | 433 | 434 | /* Render a clipped triangle in point mode */ 435 | void gl_draw_triangle_point(GLContext *c, 436 | GLVertex *p0,GLVertex *p1,GLVertex *p2) 437 | { 438 | if (p0->edge_flag) ZB_plot(c->zb,&p0->zp); 439 | if (p1->edge_flag) ZB_plot(c->zb,&p1->zp); 440 | if (p2->edge_flag) ZB_plot(c->zb,&p2->zp); 441 | } 442 | 443 | 444 | 445 | 446 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "zgl.h" 3 | 4 | void gl_fatal_error(char *format, ...) 5 | { 6 | va_list ap; 7 | 8 | va_start(ap,format); 9 | 10 | fprintf(stderr,"TinyGL: fatal error: "); 11 | vfprintf(stderr,format,ap); 12 | fprintf(stderr,"\n"); 13 | exit(1); 14 | 15 | va_end(ap); 16 | } 17 | -------------------------------------------------------------------------------- /src/get.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | void glGetIntegerv(int pname,int *params) 4 | { 5 | GLContext *c=gl_get_context(); 6 | 7 | switch(pname) { 8 | case GL_VIEWPORT: 9 | params[0]=c->viewport.xmin; 10 | params[1]=c->viewport.ymin; 11 | params[2]=c->viewport.xsize; 12 | params[3]=c->viewport.ysize; 13 | break; 14 | case GL_MAX_MODELVIEW_STACK_DEPTH: 15 | *params = MAX_MODELVIEW_STACK_DEPTH; 16 | break; 17 | case GL_MAX_PROJECTION_STACK_DEPTH: 18 | *params = MAX_PROJECTION_STACK_DEPTH; 19 | break; 20 | case GL_MAX_LIGHTS: 21 | *params = MAX_LIGHTS; 22 | break; 23 | case GL_MAX_TEXTURE_SIZE: 24 | *params = 256; /* not completely true, but... */ 25 | break; 26 | case GL_MAX_TEXTURE_STACK_DEPTH: 27 | *params = MAX_TEXTURE_STACK_DEPTH; 28 | break; 29 | default: 30 | gl_fatal_error("glGet: option not implemented"); 31 | break; 32 | } 33 | } 34 | 35 | void glGetFloatv(int pname, float *v) 36 | { 37 | int i; 38 | int mnr = 0; /* just a trick to return the correct matrix */ 39 | GLContext *c = gl_get_context(); 40 | switch (pname) { 41 | case GL_TEXTURE_MATRIX: 42 | mnr++; 43 | case GL_PROJECTION_MATRIX: 44 | mnr++; 45 | case GL_MODELVIEW_MATRIX: 46 | { 47 | float *p = &c->matrix_stack_ptr[mnr]->m[0][0];; 48 | for (i = 0; i < 4; i++) { 49 | *v++ = p[0]; 50 | *v++ = p[4]; 51 | *v++ = p[8]; 52 | *v++ = p[12]; 53 | p++; 54 | } 55 | } 56 | break; 57 | case GL_LINE_WIDTH: 58 | *v = 1.0f; 59 | break; 60 | case GL_LINE_WIDTH_RANGE: 61 | v[0] = v[1] = 1.0f; 62 | break; 63 | case GL_POINT_SIZE: 64 | *v = 1.0f; 65 | break; 66 | case GL_POINT_SIZE_RANGE: 67 | v[0] = v[1] = 1.0f; 68 | default: 69 | fprintf(stderr,"warning: unknown pname in glGetFloatv()\n"); 70 | break; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/glu.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimperator/TinySDGL/8be349298d5ad8f920ae2349549e21b06b2cf0f3/src/glu.c -------------------------------------------------------------------------------- /src/image_util.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | /* 4 | * image conversion 5 | */ 6 | 7 | void gl_convertRGB_to_5R6G5B(unsigned short *pixmap,unsigned char *rgb, 8 | int xsize,int ysize) 9 | { 10 | int i,n; 11 | unsigned char *p; 12 | 13 | p=rgb; 14 | n=xsize*ysize; 15 | for(i=0;i>3); 17 | p+=3; 18 | } 19 | } 20 | 21 | void gl_convertRGB_to_8A8R8G8B(unsigned int *pixmap, unsigned char *rgb, 22 | int xsize, int ysize) 23 | { 24 | int i,n; 25 | unsigned char *p; 26 | 27 | p=rgb; 28 | n=xsize*ysize; 29 | for(i=0;i> INTERP_NORM_BITS); 47 | } 48 | 49 | 50 | /* 51 | * TODO: more accurate resampling 52 | */ 53 | 54 | void gl_resizeImage(unsigned char *dest,int xsize_dest,int ysize_dest, 55 | unsigned char *src,int xsize_src,int ysize_src) 56 | { 57 | unsigned char *pix,*pix_src; 58 | float x1,y1,x1inc,y1inc; 59 | int xi,yi,j,xf,yf,x,y; 60 | 61 | pix=dest; 62 | pix_src=src; 63 | 64 | x1inc=(float) (xsize_src - 1) / (float) (xsize_dest - 1); 65 | y1inc=(float) (ysize_src - 1) / (float) (ysize_dest - 1); 66 | 67 | y1=0; 68 | for(y=0;y> FRAC_BITS; 123 | yi=y1 >> FRAC_BITS; 124 | pix1=pix_src+(yi*xsize_src+xi)*3; 125 | 126 | pix[0]=pix1[0]; 127 | pix[1]=pix1[1]; 128 | pix[2]=pix1[2]; 129 | 130 | pix+=3; 131 | x1+=x1inc; 132 | } 133 | y1+=y1inc; 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | GLContext *gl_ctx; 4 | 5 | 6 | void initSharedState(GLContext *c) 7 | { 8 | GLSharedState *s=&c->shared_state; 9 | s->lists=gl_zalloc(sizeof(GLList *) * MAX_DISPLAY_LISTS); 10 | s->texture_hash_table= 11 | gl_zalloc(sizeof(GLTexture *) * TEXTURE_HASH_TABLE_SIZE); 12 | 13 | alloc_texture(c,0); 14 | } 15 | 16 | void endSharedState(GLContext *c) 17 | { 18 | GLSharedState *s=&c->shared_state; 19 | int i; 20 | 21 | for(i=0;ilists); 25 | 26 | gl_free(s->texture_hash_table); 27 | } 28 | 29 | 30 | void glInit(void *zbuffer1) 31 | { 32 | ZBuffer *zbuffer=(ZBuffer *)zbuffer1; 33 | GLContext *c; 34 | GLViewport *v; 35 | int i; 36 | 37 | c=gl_zalloc(sizeof(GLContext)); 38 | gl_ctx=c; 39 | 40 | c->zb=zbuffer; 41 | 42 | /* allocate GLVertex array */ 43 | c->vertex_max = POLYGON_MAX_VERTEX; 44 | c->vertex = gl_malloc(POLYGON_MAX_VERTEX*sizeof(GLVertex)); 45 | 46 | /* viewport */ 47 | v=&c->viewport; 48 | v->xmin=0; 49 | v->ymin=0; 50 | v->xsize=zbuffer->xsize; 51 | v->ysize=zbuffer->ysize; 52 | v->updated=1; 53 | 54 | /* shared state */ 55 | initSharedState(c); 56 | 57 | /* lists */ 58 | 59 | c->exec_flag=1; 60 | c->compile_flag=0; 61 | c->print_flag=0; 62 | 63 | c->in_begin=0; 64 | 65 | /* lights */ 66 | for(i=0;ilights[i]; 68 | l->ambient=gl_V4_New(0,0,0,1); 69 | l->diffuse=gl_V4_New(1,1,1,1); 70 | l->specular=gl_V4_New(1,1,1,1); 71 | l->position=gl_V4_New(0,0,1,0); 72 | l->norm_position=gl_V3_New(0,0,1); 73 | l->spot_direction=gl_V3_New(0,0,-1); 74 | l->norm_spot_direction=gl_V3_New(0,0,-1); 75 | l->spot_exponent=0; 76 | l->spot_cutoff=180; 77 | l->attenuation[0]=1; 78 | l->attenuation[1]=0; 79 | l->attenuation[2]=0; 80 | l->enabled=0; 81 | } 82 | c->first_light=NULL; 83 | c->ambient_light_model=gl_V4_New(0.2,0.2,0.2,1); 84 | c->local_light_model=0; 85 | c->lighting_enabled=0; 86 | c->light_model_two_side = 0; 87 | 88 | /* default materials */ 89 | for(i=0;i<2;i++) { 90 | GLMaterial *m=&c->materials[i]; 91 | m->emission=gl_V4_New(0,0,0,1); 92 | m->ambient=gl_V4_New(0.2,0.2,0.2,1); 93 | m->diffuse=gl_V4_New(0.8,0.8,0.8,1); 94 | m->specular=gl_V4_New(0,0,0,1); 95 | m->shininess=0; 96 | } 97 | c->current_color_material_mode=GL_FRONT_AND_BACK; 98 | c->current_color_material_type=GL_AMBIENT_AND_DIFFUSE; 99 | c->color_material_enabled=0; 100 | 101 | /* textures */ 102 | glInitTextures(c); 103 | 104 | /* default state */ 105 | c->current_color.X=1.0; 106 | c->current_color.Y=1.0; 107 | c->current_color.Z=1.0; 108 | c->current_color.W=1.0; 109 | c->longcurrent_color[0] = 65535; 110 | c->longcurrent_color[1] = 65535; 111 | c->longcurrent_color[2] = 65535; 112 | 113 | c->current_normal.X=1.0; 114 | c->current_normal.Y=0.0; 115 | c->current_normal.Z=0.0; 116 | c->current_normal.W=0.0; 117 | 118 | c->current_edge_flag=1; 119 | 120 | c->current_tex_coord.X=0; 121 | c->current_tex_coord.Y=0; 122 | c->current_tex_coord.Z=0; 123 | c->current_tex_coord.W=1; 124 | 125 | c->polygon_mode_front=GL_FILL; 126 | c->polygon_mode_back=GL_FILL; 127 | 128 | c->current_front_face=0; /* 0 = GL_CCW 1 = GL_CW */ 129 | c->current_cull_face=GL_BACK; 130 | c->current_shade_model=GL_SMOOTH; 131 | c->cull_face_enabled=0; 132 | 133 | /* clear */ 134 | c->clear_color.v[0]=0; 135 | c->clear_color.v[1]=0; 136 | c->clear_color.v[2]=0; 137 | c->clear_color.v[3]=0; 138 | c->clear_depth=0; 139 | 140 | /* selection */ 141 | c->render_mode=GL_RENDER; 142 | c->select_buffer=NULL; 143 | c->name_stack_size=0; 144 | 145 | /* matrix */ 146 | c->matrix_mode=0; 147 | 148 | c->matrix_stack_depth_max[0]=MAX_MODELVIEW_STACK_DEPTH; 149 | c->matrix_stack_depth_max[1]=MAX_PROJECTION_STACK_DEPTH; 150 | c->matrix_stack_depth_max[2]=MAX_TEXTURE_STACK_DEPTH; 151 | 152 | for(i=0;i<3;i++) { 153 | c->matrix_stack[i]=gl_zalloc(c->matrix_stack_depth_max[i] * sizeof(M4)); 154 | c->matrix_stack_ptr[i]=c->matrix_stack[i]; 155 | } 156 | 157 | glMatrixMode(GL_PROJECTION); 158 | glLoadIdentity(); 159 | glMatrixMode(GL_TEXTURE); 160 | glLoadIdentity(); 161 | glMatrixMode(GL_MODELVIEW); 162 | glLoadIdentity(); 163 | 164 | c->matrix_model_projection_updated=1; 165 | 166 | /* opengl 1.1 arrays */ 167 | c->client_states = 0; 168 | 169 | /* opengl 1.1 polygon offset */ 170 | c->offset_states = 0; 171 | 172 | /* clear the resize callback function pointer */ 173 | c->gl_resize_viewport = NULL; 174 | 175 | /* specular buffer */ 176 | c->specbuf_first = NULL; 177 | c->specbuf_used_counter = 0; 178 | c->specbuf_num_buffers = 0; 179 | 180 | /* depth test */ 181 | c->depth_test = 0; 182 | } 183 | 184 | void glClose(void) 185 | { 186 | GLContext *c=gl_get_context(); 187 | endSharedState(c); 188 | gl_free(c); 189 | } 190 | -------------------------------------------------------------------------------- /src/light.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | #include "msghandling.h" 3 | 4 | void glopMaterial(GLContext *c,GLParam *p) 5 | { 6 | int mode=p[1].i; 7 | int type=p[2].i; 8 | float *v=&p[3].f; 9 | int i; 10 | GLMaterial *m; 11 | 12 | if (mode == GL_FRONT_AND_BACK) { 13 | p[1].i=GL_FRONT; 14 | glopMaterial(c,p); 15 | mode=GL_BACK; 16 | } 17 | if (mode == GL_FRONT) m=&c->materials[0]; 18 | else m=&c->materials[1]; 19 | 20 | switch(type) { 21 | case GL_EMISSION: 22 | for(i=0;i<4;i++) 23 | m->emission.v[i]=v[i]; 24 | break; 25 | case GL_AMBIENT: 26 | for(i=0;i<4;i++) 27 | m->ambient.v[i]=v[i]; 28 | break; 29 | case GL_DIFFUSE: 30 | for(i=0;i<4;i++) 31 | m->diffuse.v[i]=v[i]; 32 | break; 33 | case GL_SPECULAR: 34 | for(i=0;i<4;i++) 35 | m->specular.v[i]=v[i]; 36 | break; 37 | case GL_SHININESS: 38 | m->shininess=v[0]; 39 | m->shininess_i = (v[0]/128.0f)*SPECULAR_BUFFER_RESOLUTION; 40 | break; 41 | case GL_AMBIENT_AND_DIFFUSE: 42 | for(i=0;i<4;i++) 43 | m->diffuse.v[i]=v[i]; 44 | for(i=0;i<4;i++) 45 | m->ambient.v[i]=v[i]; 46 | break; 47 | default: 48 | assert(0); 49 | } 50 | } 51 | 52 | void glopColorMaterial(GLContext *c,GLParam *p) 53 | { 54 | int mode=p[1].i; 55 | int type=p[2].i; 56 | 57 | c->current_color_material_mode=mode; 58 | c->current_color_material_type=type; 59 | } 60 | 61 | void glopLight(GLContext *c,GLParam *p) 62 | { 63 | int light=p[1].i; 64 | int type=p[2].i; 65 | V4 v; 66 | GLLight *l; 67 | int i; 68 | 69 | assert(light >= GL_LIGHT0 && light < GL_LIGHT0+MAX_LIGHTS ); 70 | 71 | l=&c->lights[light-GL_LIGHT0]; 72 | 73 | for(i=0;i<4;i++) v.v[i]=p[3+i].f; 74 | 75 | switch(type) { 76 | case GL_AMBIENT: 77 | l->ambient=v; 78 | break; 79 | case GL_DIFFUSE: 80 | l->diffuse=v; 81 | break; 82 | case GL_SPECULAR: 83 | l->specular=v; 84 | break; 85 | case GL_POSITION: 86 | { 87 | V4 pos; 88 | gl_M4_MulV4(&pos,c->matrix_stack_ptr[0],&v); 89 | 90 | l->position=pos; 91 | 92 | if (l->position.v[3] == 0) { 93 | l->norm_position.X=pos.X; 94 | l->norm_position.Y=pos.Y; 95 | l->norm_position.Z=pos.Z; 96 | 97 | gl_V3_Norm(&l->norm_position); 98 | } 99 | } 100 | break; 101 | case GL_SPOT_DIRECTION: 102 | for(i=0;i<3;i++) { 103 | l->spot_direction.v[i]=v.v[i]; 104 | l->norm_spot_direction.v[i]=v.v[i]; 105 | } 106 | gl_V3_Norm(&l->norm_spot_direction); 107 | break; 108 | case GL_SPOT_EXPONENT: 109 | l->spot_exponent=v.v[0]; 110 | break; 111 | case GL_SPOT_CUTOFF: 112 | { 113 | float a=v.v[0]; 114 | assert(a == 180 || (a>=0 && a<=90)); 115 | l->spot_cutoff=a; 116 | if (a != 180) l->cos_spot_cutoff=cos(a * M_PI / 180.0); 117 | } 118 | break; 119 | case GL_CONSTANT_ATTENUATION: 120 | l->attenuation[0]=v.v[0]; 121 | break; 122 | case GL_LINEAR_ATTENUATION: 123 | l->attenuation[1]=v.v[0]; 124 | break; 125 | case GL_QUADRATIC_ATTENUATION: 126 | l->attenuation[2]=v.v[0]; 127 | break; 128 | default: 129 | assert(0); 130 | } 131 | } 132 | 133 | 134 | void glopLightModel(GLContext *c,GLParam *p) 135 | { 136 | int pname=p[1].i; 137 | float *v=&p[2].f; 138 | int i; 139 | 140 | switch(pname) { 141 | case GL_LIGHT_MODEL_AMBIENT: 142 | for(i=0;i<4;i++) 143 | c->ambient_light_model.v[i]=v[i]; 144 | break; 145 | case GL_LIGHT_MODEL_LOCAL_VIEWER: 146 | c->local_light_model=(int)v[0]; 147 | break; 148 | case GL_LIGHT_MODEL_TWO_SIDE: 149 | c->light_model_two_side = (int)v[0]; 150 | break; 151 | default: 152 | tgl_warning("glopLightModel: illegal pname: 0x%x\n", pname); 153 | //assert(0); 154 | break; 155 | } 156 | } 157 | 158 | 159 | static inline float clampf(float a,float min,float max) 160 | { 161 | if (amax) return max; 163 | else return a; 164 | } 165 | 166 | void gl_enable_disable_light(GLContext *c,int light,int v) 167 | { 168 | GLLight *l=&c->lights[light]; 169 | if (v && !l->enabled) { 170 | l->enabled=1; 171 | l->next=c->first_light; 172 | c->first_light=l; 173 | l->prev=NULL; 174 | } else if (!v && l->enabled) { 175 | l->enabled=0; 176 | if (l->prev == NULL) c->first_light=l->next; 177 | else l->prev->next=l->next; 178 | if (l->next != NULL) l->next->prev=l->prev; 179 | } 180 | } 181 | 182 | /* non optimized lightening model */ 183 | void gl_shade_vertex(GLContext *c,GLVertex *v) 184 | { 185 | float R,G,B,A; 186 | GLMaterial *m; 187 | GLLight *l; 188 | V3 n,s,d; 189 | float dist,tmp,att,dot,dot_spot,dot_spec; 190 | int twoside = c->light_model_two_side; 191 | 192 | m=&c->materials[0]; 193 | 194 | n.X=v->normal.X; 195 | n.Y=v->normal.Y; 196 | n.Z=v->normal.Z; 197 | 198 | R=m->emission.v[0]+m->ambient.v[0]*c->ambient_light_model.v[0]; 199 | G=m->emission.v[1]+m->ambient.v[1]*c->ambient_light_model.v[1]; 200 | B=m->emission.v[2]+m->ambient.v[2]*c->ambient_light_model.v[2]; 201 | A=clampf(m->diffuse.v[3],0,1); 202 | 203 | for(l=c->first_light;l!=NULL;l=l->next) { 204 | float lR,lB,lG; 205 | 206 | /* ambient */ 207 | lR=l->ambient.v[0] * m->ambient.v[0]; 208 | lG=l->ambient.v[1] * m->ambient.v[1]; 209 | lB=l->ambient.v[2] * m->ambient.v[2]; 210 | 211 | if (l->position.v[3] == 0) { 212 | /* light at infinity */ 213 | d.X=l->position.v[0]; 214 | d.Y=l->position.v[1]; 215 | d.Z=l->position.v[2]; 216 | att=1; 217 | } else { 218 | /* distance attenuation */ 219 | d.X=l->position.v[0]-v->ec.v[0]; 220 | d.Y=l->position.v[1]-v->ec.v[1]; 221 | d.Z=l->position.v[2]-v->ec.v[2]; 222 | dist=sqrt(d.X*d.X+d.Y*d.Y+d.Z*d.Z); 223 | if (dist>1E-3) { 224 | tmp=1/dist; 225 | d.X*=tmp; 226 | d.Y*=tmp; 227 | d.Z*=tmp; 228 | } 229 | att=1.0f/(l->attenuation[0]+dist*(l->attenuation[1]+ 230 | dist*l->attenuation[2])); 231 | } 232 | dot=d.X*n.X+d.Y*n.Y+d.Z*n.Z; 233 | if (twoside && dot < 0) dot = -dot; 234 | if (dot>0) { 235 | /* diffuse light */ 236 | lR+=dot * l->diffuse.v[0] * m->diffuse.v[0]; 237 | lG+=dot * l->diffuse.v[1] * m->diffuse.v[1]; 238 | lB+=dot * l->diffuse.v[2] * m->diffuse.v[2]; 239 | 240 | /* spot light */ 241 | if (l->spot_cutoff != 180) { 242 | dot_spot=-(d.X*l->norm_spot_direction.v[0]+ 243 | d.Y*l->norm_spot_direction.v[1]+ 244 | d.Z*l->norm_spot_direction.v[2]); 245 | if (twoside && dot_spot < 0) dot_spot = -dot_spot; 246 | if (dot_spot < l->cos_spot_cutoff) { 247 | /* no contribution */ 248 | continue; 249 | } else { 250 | /* TODO: optimize */ 251 | if (l->spot_exponent > 0) { 252 | att=att*pow(dot_spot,l->spot_exponent); 253 | } 254 | } 255 | } 256 | 257 | /* specular light */ 258 | 259 | if (c->local_light_model) { 260 | V3 vcoord; 261 | vcoord.X=v->ec.X; 262 | vcoord.Y=v->ec.Y; 263 | vcoord.Z=v->ec.Z; 264 | gl_V3_Norm(&vcoord); 265 | s.X=d.X-vcoord.X; 266 | s.Y=d.Y-vcoord.X; 267 | s.Z=d.Z-vcoord.X; 268 | } else { 269 | s.X=d.X; 270 | s.Y=d.Y; 271 | s.Z=d.Z+1.0; 272 | } 273 | dot_spec=n.X*s.X+n.Y*s.Y+n.Z*s.Z; 274 | if (twoside && dot_spec < 0) dot_spec = -dot_spec; 275 | if (dot_spec>0) { 276 | GLSpecBuf *specbuf; 277 | int idx; 278 | tmp=sqrt(s.X*s.X+s.Y*s.Y+s.Z*s.Z); 279 | if (tmp > 1E-3) { 280 | dot_spec=dot_spec / tmp; 281 | } 282 | 283 | /* TODO: optimize */ 284 | /* testing specular buffer code */ 285 | /* dot_spec= pow(dot_spec,m->shininess);*/ 286 | specbuf = specbuf_get_buffer(c, m->shininess_i, m->shininess); 287 | idx = (int)(dot_spec*SPECULAR_BUFFER_SIZE); 288 | if (idx > SPECULAR_BUFFER_SIZE) idx = SPECULAR_BUFFER_SIZE; 289 | dot_spec = specbuf->buf[idx]; 290 | lR+=dot_spec * l->specular.v[0] * m->specular.v[0]; 291 | lG+=dot_spec * l->specular.v[1] * m->specular.v[1]; 292 | lB+=dot_spec * l->specular.v[2] * m->specular.v[2]; 293 | } 294 | } 295 | 296 | R+=att * lR; 297 | G+=att * lG; 298 | B+=att * lB; 299 | } 300 | 301 | v->color.v[0]=clampf(R,0,1); 302 | v->color.v[1]=clampf(G,0,1); 303 | v->color.v[2]=clampf(B,0,1); 304 | v->color.v[3]=A; 305 | } 306 | 307 | -------------------------------------------------------------------------------- /src/list.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | static char *op_table_str[]= 4 | { 5 | #define ADD_OP(a,b,c) "gl" #a " " #c, 6 | 7 | #include "opinfo.h" 8 | }; 9 | 10 | static void (*op_table_func[])(GLContext *,GLParam *)= 11 | { 12 | #define ADD_OP(a,b,c) glop ## a , 13 | 14 | #include "opinfo.h" 15 | }; 16 | 17 | static int op_table_size[]= 18 | { 19 | #define ADD_OP(a,b,c) b + 1 , 20 | 21 | #include "opinfo.h" 22 | }; 23 | 24 | 25 | GLContext *gl_get_context(void) 26 | { 27 | return gl_ctx; 28 | } 29 | 30 | static GLList *find_list(GLContext *c,unsigned int list) 31 | { 32 | return c->shared_state.lists[list]; 33 | } 34 | 35 | static void delete_list(GLContext *c,int list) 36 | { 37 | GLParamBuffer *pb,*pb1; 38 | GLList *l; 39 | 40 | l=find_list(c,list); 41 | assert(l != NULL); 42 | 43 | /* free param buffer */ 44 | pb=l->first_op_buffer; 45 | while (pb!=NULL) { 46 | pb1=pb->next; 47 | gl_free(pb); 48 | pb=pb1; 49 | } 50 | 51 | gl_free(l); 52 | c->shared_state.lists[list]=NULL; 53 | } 54 | 55 | static GLList *alloc_list(GLContext *c,int list) 56 | { 57 | GLList *l; 58 | GLParamBuffer *ob; 59 | 60 | l=gl_zalloc(sizeof(GLList)); 61 | ob=gl_zalloc(sizeof(GLParamBuffer)); 62 | 63 | ob->next=NULL; 64 | l->first_op_buffer=ob; 65 | 66 | ob->ops[0].op=OP_EndList; 67 | 68 | c->shared_state.lists[list]=l; 69 | return l; 70 | } 71 | 72 | 73 | void gl_print_op(FILE *f,GLParam *p) 74 | { 75 | int op; 76 | char *s; 77 | 78 | op=p[0].op; 79 | p++; 80 | s=op_table_str[op]; 81 | while (*s != 0) { 82 | if (*s == '%') { 83 | s++; 84 | switch (*s++) { 85 | case 'f': 86 | fprintf(f,"%g",p[0].f); 87 | break; 88 | default: 89 | fprintf(f,"%d",p[0].i); 90 | break; 91 | } 92 | p++; 93 | } else { 94 | fputc(*s,f); 95 | s++; 96 | } 97 | } 98 | fprintf(f,"\n"); 99 | } 100 | 101 | 102 | void gl_compile_op(GLContext *c,GLParam *p) 103 | { 104 | int op,op_size; 105 | GLParamBuffer *ob,*ob1; 106 | int index,i; 107 | 108 | op=p[0].op; 109 | op_size=op_table_size[op]; 110 | index=c->current_op_buffer_index; 111 | ob=c->current_op_buffer; 112 | 113 | /* we should be able to add a NextBuffer opcode */ 114 | if ((index + op_size) > (OP_BUFFER_MAX_SIZE-2)) { 115 | 116 | ob1=gl_zalloc(sizeof(GLParamBuffer)); 117 | ob1->next=NULL; 118 | 119 | ob->next=ob1; 120 | ob->ops[index].op=OP_NextBuffer; 121 | ob->ops[index+1].p=(void *)ob1; 122 | 123 | c->current_op_buffer=ob1; 124 | ob=ob1; 125 | index=0; 126 | } 127 | 128 | for(i=0;iops[index]=p[i]; 130 | index++; 131 | } 132 | c->current_op_buffer_index=index; 133 | } 134 | 135 | void gl_add_op(GLParam *p) 136 | { 137 | GLContext *c=gl_get_context(); 138 | int op; 139 | 140 | op=p[0].op; 141 | if (c->exec_flag) { 142 | op_table_func[op](c,p); 143 | } 144 | if (c->compile_flag) { 145 | gl_compile_op(c,p); 146 | } 147 | if (c->print_flag) { 148 | gl_print_op(stderr,p); 149 | } 150 | } 151 | 152 | /* this opcode is never called directly */ 153 | void glopEndList(GLContext *c,GLParam *p) 154 | { 155 | assert(0); 156 | } 157 | 158 | /* this opcode is never called directly */ 159 | void glopNextBuffer(GLContext *c,GLParam *p) 160 | { 161 | assert(0); 162 | } 163 | 164 | 165 | void glopCallList(GLContext *c,GLParam *p) 166 | { 167 | GLList *l; 168 | int list,op; 169 | 170 | list=p[1].ui; 171 | l=find_list(c,list); 172 | if (l == NULL) gl_fatal_error("list %d not defined",list); 173 | p=l->first_op_buffer->ops; 174 | 175 | while (1) { 176 | op=p[0].op; 177 | if (op == OP_EndList) break; 178 | if (op == OP_NextBuffer) { 179 | p=(GLParam *)p[1].p; 180 | } else { 181 | op_table_func[op](c,p); 182 | p+=op_table_size[op]; 183 | } 184 | } 185 | } 186 | 187 | 188 | 189 | void glNewList(unsigned int list,int mode) 190 | { 191 | GLList *l; 192 | GLContext *c=gl_get_context(); 193 | 194 | assert(mode == GL_COMPILE || mode == GL_COMPILE_AND_EXECUTE); 195 | assert(c->compile_flag == 0); 196 | 197 | l=find_list(c,list); 198 | if (l!=NULL) delete_list(c,list); 199 | l=alloc_list(c,list); 200 | 201 | c->current_op_buffer=l->first_op_buffer; 202 | c->current_op_buffer_index=0; 203 | 204 | c->compile_flag=1; 205 | c->exec_flag=(mode == GL_COMPILE_AND_EXECUTE); 206 | } 207 | 208 | void glEndList(void) 209 | { 210 | GLContext *c=gl_get_context(); 211 | GLParam p[1]; 212 | 213 | assert(c->compile_flag == 1); 214 | 215 | /* end of list */ 216 | p[0].op=OP_EndList; 217 | gl_compile_op(c,p); 218 | 219 | c->compile_flag=0; 220 | c->exec_flag=1; 221 | } 222 | 223 | int glIsList(unsigned int list) 224 | { 225 | GLContext *c=gl_get_context(); 226 | GLList *l; 227 | l=find_list(c,list); 228 | return (l != NULL); 229 | } 230 | 231 | unsigned int glGenLists(int range) 232 | { 233 | GLContext *c=gl_get_context(); 234 | int count,i,list; 235 | GLList **lists; 236 | 237 | lists=c->shared_state.lists; 238 | count=0; 239 | for(i=0;imatrix_model_projection_updated=(c->matrix_mode<=1); 15 | } 16 | 17 | 18 | void glopMatrixMode(GLContext *c,GLParam *p) 19 | { 20 | int mode=p[1].i; 21 | switch(mode) { 22 | case GL_MODELVIEW: 23 | c->matrix_mode=0; 24 | break; 25 | case GL_PROJECTION: 26 | c->matrix_mode=1; 27 | break; 28 | case GL_TEXTURE: 29 | c->matrix_mode=2; 30 | break; 31 | default: 32 | assert(0); 33 | } 34 | } 35 | 36 | void glopLoadMatrix(GLContext *c,GLParam *p) 37 | { 38 | M4 *m; 39 | int i; 40 | 41 | GLParam *q; 42 | 43 | m=c->matrix_stack_ptr[c->matrix_mode]; 44 | q=p+1; 45 | 46 | for(i=0;i<4;i++) { 47 | m->m[0][i]=q[0].f; 48 | m->m[1][i]=q[1].f; 49 | m->m[2][i]=q[2].f; 50 | m->m[3][i]=q[3].f; 51 | q+=4; 52 | } 53 | 54 | gl_matrix_update(c); 55 | } 56 | 57 | void glopLoadIdentity(GLContext *c,GLParam *p) 58 | { 59 | 60 | gl_M4_Id(c->matrix_stack_ptr[c->matrix_mode]); 61 | 62 | gl_matrix_update(c); 63 | } 64 | 65 | void glopMultMatrix(GLContext *c,GLParam *p) 66 | { 67 | M4 m; 68 | int i; 69 | 70 | GLParam *q; 71 | q=p+1; 72 | 73 | for(i=0;i<4;i++) { 74 | m.m[0][i]=q[0].f; 75 | m.m[1][i]=q[1].f; 76 | m.m[2][i]=q[2].f; 77 | m.m[3][i]=q[3].f; 78 | q+=4; 79 | } 80 | 81 | gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); 82 | 83 | gl_matrix_update(c); 84 | } 85 | 86 | 87 | void glopPushMatrix(GLContext *c,GLParam *p) 88 | { 89 | int n=c->matrix_mode; 90 | M4 *m; 91 | 92 | assert( (c->matrix_stack_ptr[n] - c->matrix_stack[n] + 1 ) 93 | < c->matrix_stack_depth_max[n] ); 94 | 95 | m=++c->matrix_stack_ptr[n]; 96 | 97 | gl_M4_Move(&m[0],&m[-1]); 98 | 99 | gl_matrix_update(c); 100 | } 101 | 102 | void glopPopMatrix(GLContext *c,GLParam *p) 103 | { 104 | int n=c->matrix_mode; 105 | 106 | assert( c->matrix_stack_ptr[n] > c->matrix_stack[n] ); 107 | c->matrix_stack_ptr[n]--; 108 | gl_matrix_update(c); 109 | } 110 | 111 | 112 | void glopRotate(GLContext *c,GLParam *p) 113 | { 114 | M4 m; 115 | float u[3]; 116 | float angle; 117 | int dir_code; 118 | 119 | angle = p[1].f * M_PI / 180.0; 120 | u[0]=p[2].f; 121 | u[1]=p[3].f; 122 | u[2]=p[4].f; 123 | 124 | /* simple case detection */ 125 | dir_code = ((u[0] != 0)<<2) | ((u[1] != 0)<<1) | (u[2] != 0); 126 | 127 | switch(dir_code) { 128 | case 0: 129 | gl_M4_Id(&m); 130 | break; 131 | case 4: 132 | if (u[0] < 0) angle=-angle; 133 | gl_M4_Rotate(&m,angle,0); 134 | break; 135 | case 2: 136 | if (u[1] < 0) angle=-angle; 137 | gl_M4_Rotate(&m,angle,1); 138 | break; 139 | case 1: 140 | if (u[2] < 0) angle=-angle; 141 | gl_M4_Rotate(&m,angle,2); 142 | break; 143 | default: 144 | { 145 | float cost, sint; 146 | 147 | /* normalize vector */ 148 | float len = u[0]*u[0]+u[1]*u[1]+u[2]*u[2]; 149 | if (len == 0.0f) return; 150 | len = 1.0f / sqrt(len); 151 | u[0] *= len; 152 | u[1] *= len; 153 | u[2] *= len; 154 | 155 | /* store cos and sin values */ 156 | cost=cos(angle); 157 | sint=sin(angle); 158 | 159 | /* fill in the values */ 160 | m.m[3][0]=m.m[3][1]=m.m[3][2]= 161 | m.m[0][3]=m.m[1][3]=m.m[2][3]=0.0f; 162 | m.m[3][3]=1.0f; 163 | 164 | /* do the math */ 165 | m.m[0][0]=u[0]*u[0]+cost*(1-u[0]*u[0]); 166 | m.m[1][0]=u[0]*u[1]*(1-cost)-u[2]*sint; 167 | m.m[2][0]=u[2]*u[0]*(1-cost)+u[1]*sint; 168 | m.m[0][1]=u[0]*u[1]*(1-cost)+u[2]*sint; 169 | m.m[1][1]=u[1]*u[1]+cost*(1-u[1]*u[1]); 170 | m.m[2][1]=u[1]*u[2]*(1-cost)-u[0]*sint; 171 | m.m[0][2]=u[2]*u[0]*(1-cost)-u[1]*sint; 172 | m.m[1][2]=u[1]*u[2]*(1-cost)+u[0]*sint; 173 | m.m[2][2]=u[2]*u[2]+cost*(1-u[2]*u[2]); 174 | } 175 | } 176 | 177 | gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); 178 | 179 | gl_matrix_update(c); 180 | } 181 | 182 | void glopScale(GLContext *c,GLParam *p) 183 | { 184 | float *m; 185 | float x=p[1].f,y=p[2].f,z=p[3].f; 186 | 187 | m=&c->matrix_stack_ptr[c->matrix_mode]->m[0][0]; 188 | 189 | m[0] *= x; m[1] *= y; m[2] *= z; 190 | m[4] *= x; m[5] *= y; m[6] *= z; 191 | m[8] *= x; m[9] *= y; m[10] *= z; 192 | m[12] *= x; m[13] *= y; m[14] *= z; 193 | gl_matrix_update(c); 194 | } 195 | 196 | void glopTranslate(GLContext *c,GLParam *p) 197 | { 198 | float *m; 199 | float x=p[1].f,y=p[2].f,z=p[3].f; 200 | 201 | m=&c->matrix_stack_ptr[c->matrix_mode]->m[0][0]; 202 | 203 | m[3] = m[0] * x + m[1] * y + m[2] * z + m[3]; 204 | m[7] = m[4] * x + m[5] * y + m[6] * z + m[7]; 205 | m[11] = m[8] * x + m[9] * y + m[10] * z + m[11]; 206 | m[15] = m[12] * x + m[13] * y + m[14] * z + m[15]; 207 | 208 | gl_matrix_update(c); 209 | } 210 | 211 | 212 | void glopFrustum(GLContext *c,GLParam *p) 213 | { 214 | float *r; 215 | M4 m; 216 | float left=p[1].f; 217 | float right=p[2].f; 218 | float bottom=p[3].f; 219 | float top=p[4].f; 220 | float near=p[5].f; 221 | float farp=p[6].f; 222 | float x,y,A,B,C,D; 223 | 224 | x = (2.0*near) / (right-left); 225 | y = (2.0*near) / (top-bottom); 226 | A = (right+left) / (right-left); 227 | B = (top+bottom) / (top-bottom); 228 | C = -(farp+near) / ( farp-near); 229 | D = -(2.0*farp*near) / (farp-near); 230 | 231 | r=&m.m[0][0]; 232 | r[0]= x; r[1]=0; r[2]=A; r[3]=0; 233 | r[4]= 0; r[5]=y; r[6]=B; r[7]=0; 234 | r[8]= 0; r[9]=0; r[10]=C; r[11]=D; 235 | r[12]= 0; r[13]=0; r[14]=-1; r[15]=0; 236 | 237 | gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); 238 | 239 | gl_matrix_update(c); 240 | } 241 | 242 | -------------------------------------------------------------------------------- /src/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Memory allocator for TinyGL 3 | */ 4 | #include "zgl.h" 5 | 6 | /* modify these functions so that they suit your needs */ 7 | 8 | void gl_free(void *p) 9 | { 10 | free(p); 11 | } 12 | 13 | void *gl_malloc(int size) 14 | { 15 | return malloc(size); 16 | } 17 | 18 | void *gl_zalloc(int size) 19 | { 20 | return calloc(1, size); 21 | } 22 | -------------------------------------------------------------------------------- /src/misc.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | #include "msghandling.h" 3 | 4 | void glopViewport(GLContext *c,GLParam *p) 5 | { 6 | int xsize,ysize,xmin,ymin,xsize_req,ysize_req; 7 | 8 | xmin=p[1].i; 9 | ymin=p[2].i; 10 | xsize=p[3].i; 11 | ysize=p[4].i; 12 | 13 | /* we may need to resize the zbuffer */ 14 | 15 | if (c->viewport.xmin != xmin || 16 | c->viewport.ymin != ymin || 17 | c->viewport.xsize != xsize || 18 | c->viewport.ysize != ysize) { 19 | 20 | xsize_req=xmin+xsize; 21 | ysize_req=ymin+ysize; 22 | 23 | if (c->gl_resize_viewport && 24 | c->gl_resize_viewport(c,&xsize_req,&ysize_req) != 0) { 25 | gl_fatal_error("glViewport: error while resizing display"); 26 | } 27 | 28 | xsize=xsize_req-xmin; 29 | ysize=ysize_req-ymin; 30 | if (xsize <= 0 || ysize <= 0) { 31 | gl_fatal_error("glViewport: size too small"); 32 | } 33 | 34 | tgl_trace("glViewport: %d %d %d %d\n", 35 | xmin, ymin, xsize, ysize); 36 | c->viewport.xmin=xmin; 37 | c->viewport.ymin=ymin; 38 | c->viewport.xsize=xsize; 39 | c->viewport.ysize=ysize; 40 | 41 | c->viewport.updated=1; 42 | } 43 | } 44 | 45 | void glopEnableDisable(GLContext *c,GLParam *p) 46 | { 47 | int code=p[1].i; 48 | int v=p[2].i; 49 | 50 | switch(code) { 51 | case GL_CULL_FACE: 52 | c->cull_face_enabled=v; 53 | break; 54 | case GL_LIGHTING: 55 | c->lighting_enabled=v; 56 | break; 57 | case GL_COLOR_MATERIAL: 58 | c->color_material_enabled=v; 59 | break; 60 | case GL_TEXTURE_2D: 61 | c->texture_2d_enabled=v; 62 | break; 63 | case GL_NORMALIZE: 64 | c->normalize_enabled=v; 65 | break; 66 | case GL_DEPTH_TEST: 67 | c->depth_test = v; 68 | break; 69 | case GL_POLYGON_OFFSET_FILL: 70 | if (v) c->offset_states |= TGL_OFFSET_FILL; 71 | else c->offset_states &= ~TGL_OFFSET_FILL; 72 | break; 73 | case GL_POLYGON_OFFSET_POINT: 74 | if (v) c->offset_states |= TGL_OFFSET_POINT; 75 | else c->offset_states &= ~TGL_OFFSET_POINT; 76 | break; 77 | case GL_POLYGON_OFFSET_LINE: 78 | if (v) c->offset_states |= TGL_OFFSET_LINE; 79 | else c->offset_states &= ~TGL_OFFSET_LINE; 80 | break; 81 | default: 82 | if (code>=GL_LIGHT0 && codecurrent_shade_model=code; 97 | } 98 | 99 | void glopCullFace(GLContext *c,GLParam *p) 100 | { 101 | int code=p[1].i; 102 | c->current_cull_face=code; 103 | } 104 | 105 | void glopFrontFace(GLContext *c,GLParam *p) 106 | { 107 | int code=p[1].i; 108 | c->current_front_face=code; 109 | } 110 | 111 | void glopPolygonMode(GLContext *c,GLParam *p) 112 | { 113 | int face=p[1].i; 114 | int mode=p[2].i; 115 | 116 | switch(face) { 117 | case GL_BACK: 118 | c->polygon_mode_back=mode; 119 | break; 120 | case GL_FRONT: 121 | c->polygon_mode_front=mode; 122 | break; 123 | case GL_FRONT_AND_BACK: 124 | c->polygon_mode_front=mode; 125 | c->polygon_mode_back=mode; 126 | break; 127 | default: 128 | assert(0); 129 | } 130 | } 131 | 132 | void glopHint(GLContext *c,GLParam *p) 133 | { 134 | #if 0 135 | int target=p[1].i; 136 | int mode=p[2].i; 137 | 138 | /* do nothing */ 139 | #endif 140 | } 141 | 142 | void 143 | glopPolygonOffset(GLContext *c, GLParam *p) 144 | { 145 | c->offset_factor = p[1].f; 146 | c->offset_units = p[2].f; 147 | } 148 | -------------------------------------------------------------------------------- /src/msghandling.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define NDEBUG 5 | 6 | #ifdef NDEBUG 7 | #define NO_DEBUG_OUTPUT 8 | #endif 9 | 10 | /* Use this function to output messages when something unexpected 11 | happens (which might be an indication of an error). *Don't* use it 12 | when there's internal errors in the code - these should be handled 13 | by asserts. */ 14 | void 15 | tgl_warning(const char *format, ...) 16 | { 17 | #ifndef NO_DEBUG_OUTPUT 18 | va_list args; 19 | va_start(args, format); 20 | fprintf(stderr, "*WARNING* "); 21 | vfprintf(stderr, format, args); 22 | va_end(args); 23 | #endif /* !NO_DEBUG_OUTPUT */ 24 | } 25 | 26 | /* This function should be used for debug output only. */ 27 | void 28 | tgl_trace(const char *format, ...) 29 | { 30 | #ifndef NO_DEBUG_OUTPUT 31 | va_list args; 32 | va_start(args, format); 33 | fprintf(stderr, "*DEBUG* "); 34 | vfprintf(stderr, format, args); 35 | va_end(args); 36 | #endif /* !NO_DEBUG_OUTPUT */ 37 | } 38 | 39 | /* Use this function to output info about things in the code which 40 | should be fixed (missing handling of special cases, important 41 | features not implemented, known bugs/buglets, ...). */ 42 | void 43 | tgl_fixme(const char *format, ...) 44 | { 45 | #ifndef NO_DEBUG_OUTPUT 46 | va_list args; 47 | va_start(args, format); 48 | fprintf(stderr, "*FIXME* "); 49 | vfprintf(stderr, format, args); 50 | va_end(args); 51 | #endif /* !NO_DEBUG_OUTPUT */ 52 | } 53 | -------------------------------------------------------------------------------- /src/msghandling.h: -------------------------------------------------------------------------------- 1 | #ifndef _msghandling_h_ 2 | #define _msghandling_h_ 3 | 4 | extern void tgl_warning(const char *text, ...); 5 | extern void tgl_trace(const char *text, ...); 6 | extern void tgl_fixme(const char *text, ...); 7 | 8 | #endif /* _msghandling_h_ */ 9 | -------------------------------------------------------------------------------- /src/opinfo.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | ADD_OP(Color,7,"%f %f %f %f %d %d %d") 4 | ADD_OP(TexCoord,4,"%f %f %f %f") 5 | ADD_OP(EdgeFlag,1,"%d") 6 | ADD_OP(Normal,3,"%f %f %f") 7 | 8 | ADD_OP(Begin,1,"%C") 9 | ADD_OP(Vertex,4,"%f %f %f %f") 10 | ADD_OP(End,0,"") 11 | 12 | ADD_OP(EnableDisable,2,"%C %d") 13 | 14 | ADD_OP(MatrixMode,1,"%C") 15 | ADD_OP(LoadMatrix,16,"") 16 | ADD_OP(LoadIdentity,0,"") 17 | ADD_OP(MultMatrix,16,"") 18 | ADD_OP(PushMatrix,0,"") 19 | ADD_OP(PopMatrix,0,"") 20 | ADD_OP(Rotate,4,"%f %f %f %f") 21 | ADD_OP(Translate,3,"%f %f %f") 22 | ADD_OP(Scale,3,"%f %f %f") 23 | 24 | ADD_OP(Viewport,4,"%d %d %d %d") 25 | ADD_OP(Frustum,6,"%f %f %f %f %f %f") 26 | 27 | ADD_OP(Material,6,"%C %C %f %f %f %f") 28 | ADD_OP(ColorMaterial,2,"%C %C") 29 | ADD_OP(Light,6,"%C %C %f %f %f %f") 30 | ADD_OP(LightModel,5,"%C %f %f %f %f") 31 | 32 | ADD_OP(Clear,1,"%d") 33 | ADD_OP(ClearColor,4,"%f %f %f %f") 34 | ADD_OP(ClearDepth,1,"%f") 35 | 36 | ADD_OP(InitNames,0,"") 37 | ADD_OP(PushName,1,"%d") 38 | ADD_OP(PopName,0,"") 39 | ADD_OP(LoadName,1,"%d") 40 | 41 | ADD_OP(TexImage2D,9,"%d %d %d %d %d %d %d %d %d") 42 | ADD_OP(BindTexture,2,"%C %d") 43 | ADD_OP(TexEnv,7,"%C %C %C %f %f %f %f") 44 | ADD_OP(TexParameter,7,"%C %C %C %f %f %f %f") 45 | ADD_OP(PixelStore,2,"%C %C") 46 | 47 | ADD_OP(ShadeModel,1,"%C") 48 | ADD_OP(CullFace,1,"%C") 49 | ADD_OP(FrontFace,1,"%C") 50 | ADD_OP(PolygonMode,2,"%C %C") 51 | 52 | ADD_OP(CallList,1,"%d") 53 | ADD_OP(Hint,2,"%C %C") 54 | 55 | /* special opcodes */ 56 | ADD_OP(EndList,0,"") 57 | ADD_OP(NextBuffer,1,"%p") 58 | 59 | /* opengl 1.1 arrays */ 60 | ADD_OP(ArrayElement, 1, "%d") 61 | ADD_OP(EnableClientState, 1, "%C") 62 | ADD_OP(DisableClientState, 1, "%C") 63 | ADD_OP(VertexPointer, 4, "%d %C %d %p") 64 | ADD_OP(ColorPointer, 4, "%d %C %d %p") 65 | ADD_OP(NormalPointer, 3, "%C %d %p") 66 | ADD_OP(TexCoordPointer, 4, "%d %C %d %p") 67 | 68 | /* opengl 1.1 polygon offset */ 69 | ADD_OP(PolygonOffset, 2, "%f %f") 70 | 71 | #undef ADD_OP 72 | -------------------------------------------------------------------------------- /src/oscontext.c: -------------------------------------------------------------------------------- 1 | #include "oscontext.h" 2 | #include "zbuffer.h" 3 | #include "zgl.h" 4 | #include 5 | #include 6 | #include 7 | 8 | static int buffercnt = 0; 9 | 10 | ostgl_context * 11 | ostgl_create_context(const int xsize, 12 | const int ysize, 13 | const int depth, 14 | void **framebuffers, 15 | const int numbuffers) 16 | { 17 | ostgl_context *context; 18 | int i; 19 | ZBuffer *zb; 20 | 21 | assert(depth == 16); /* support for other depths must include bpp 22 | convertion */ 23 | assert(numbuffers >= 1); 24 | 25 | context = gl_malloc(sizeof(ostgl_context)); 26 | assert(context); 27 | context->zbs = gl_malloc(sizeof(void*)*numbuffers); 28 | context->framebuffers = gl_malloc(sizeof(void*)*numbuffers); 29 | 30 | assert(context->zbs != NULL && context->framebuffers != NULL); 31 | 32 | for (i = 0; i < numbuffers; i++) { 33 | context->framebuffers[i] = framebuffers[i]; 34 | zb = ZB_open(xsize, ysize, ZB_MODE_5R6G5B, 0, NULL, NULL, framebuffers[i]); 35 | if (zb == NULL) { 36 | fprintf(stderr, "Error while initializing Z buffer\n"); 37 | exit(1); 38 | } 39 | context->zbs[i] = zb; 40 | } 41 | if (++buffercnt == 1) { 42 | glInit(context->zbs[0]); 43 | } 44 | context->xsize = xsize; 45 | context->ysize = ysize; 46 | context->numbuffers = numbuffers; 47 | return context; 48 | } 49 | 50 | void 51 | ostgl_delete_context(ostgl_context *context) 52 | { 53 | int i; 54 | for (i = 0; i < context->numbuffers; i++) { 55 | ZB_close(context->zbs[i]); 56 | } 57 | gl_free(context->zbs); 58 | gl_free(context->framebuffers); 59 | gl_free(context); 60 | 61 | if (--buffercnt == 0) { 62 | glClose(); 63 | } 64 | } 65 | 66 | void 67 | ostgl_make_current(ostgl_context *oscontext, const int idx) 68 | { 69 | GLContext *context = gl_get_context(); 70 | assert(idx < oscontext->numbuffers); 71 | context->zb = oscontext->zbs[idx]; 72 | } 73 | 74 | void 75 | ostgl_resize(ostgl_context *context, 76 | const int xsize, 77 | const int ysize, 78 | void **framebuffers) 79 | { 80 | int i; 81 | for (i = 0; i < context->numbuffers; i++) { 82 | ZB_resize(context->zbs[i], framebuffers[i], xsize, ysize); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/oscontext.h: -------------------------------------------------------------------------------- 1 | #ifndef _tgl_osbuffer_h_ 2 | #define _tgl_osbuffer_h_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct { 9 | void **zbs; 10 | void **framebuffers; 11 | int numbuffers; 12 | int xsize, ysize; 13 | } ostgl_context; 14 | 15 | ostgl_context * 16 | ostgl_create_context(const int xsize, 17 | const int ysize, 18 | const int depth, 19 | void **framebuffers, 20 | const int numbuffers); 21 | void 22 | ostgl_delete_context(ostgl_context *context); 23 | 24 | void 25 | ostgl_make_current(ostgl_context *context, const int index); 26 | 27 | void 28 | ostgl_resize(ostgl_context * context, 29 | const int xsize, 30 | const int ysize, 31 | void **framebuffers); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif /* _tgl_osbuffer_h_ */ 38 | -------------------------------------------------------------------------------- /src/select.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | 3 | int glRenderMode(int mode) 4 | { 5 | GLContext *c=gl_get_context(); 6 | int result=0; 7 | 8 | switch(c->render_mode) { 9 | case GL_RENDER: 10 | break; 11 | case GL_SELECT: 12 | if (c->select_overflow) { 13 | result=-c->select_hits; 14 | } else { 15 | result=c->select_hits; 16 | } 17 | c->select_overflow=0; 18 | c->select_ptr=c->select_buffer; 19 | c->name_stack_size=0; 20 | break; 21 | default: 22 | assert(0); 23 | } 24 | switch(mode) { 25 | case GL_RENDER: 26 | c->render_mode=GL_RENDER; 27 | break; 28 | case GL_SELECT: 29 | c->render_mode=GL_SELECT; 30 | assert( c->select_buffer != NULL); 31 | c->select_ptr=c->select_buffer; 32 | c->select_hits=0; 33 | c->select_overflow=0; 34 | c->select_hit=NULL; 35 | break; 36 | default: 37 | assert(0); 38 | } 39 | return result; 40 | } 41 | 42 | void glSelectBuffer(int size,unsigned int *buf) 43 | { 44 | GLContext *c=gl_get_context(); 45 | 46 | assert(c->render_mode != GL_SELECT); 47 | 48 | c->select_buffer=buf; 49 | c->select_size=size; 50 | } 51 | 52 | 53 | void glopInitNames(GLContext *c,GLParam *p) 54 | { 55 | if (c->render_mode == GL_SELECT) { 56 | c->name_stack_size=0; 57 | c->select_hit=NULL; 58 | } 59 | } 60 | 61 | void glopPushName(GLContext *c,GLParam *p) 62 | { 63 | if (c->render_mode == GL_SELECT) { 64 | assert(c->name_stack_sizename_stack[c->name_stack_size++]=p[1].i; 66 | c->select_hit=NULL; 67 | } 68 | } 69 | 70 | void glopPopName(GLContext *c,GLParam *p) 71 | { 72 | if (c->render_mode == GL_SELECT) { 73 | assert(c->name_stack_size>0); 74 | c->name_stack_size--; 75 | c->select_hit=NULL; 76 | } 77 | } 78 | 79 | void glopLoadName(GLContext *c,GLParam *p) 80 | { 81 | if (c->render_mode == GL_SELECT) { 82 | assert(c->name_stack_size>0); 83 | c->name_stack[c->name_stack_size-1]=p[1].i; 84 | c->select_hit=NULL; 85 | } 86 | } 87 | 88 | void gl_add_select(GLContext *c,unsigned int zmin,unsigned int zmax) 89 | { 90 | unsigned int *ptr; 91 | int n,i; 92 | 93 | if (!c->select_overflow) { 94 | if (c->select_hit==NULL) { 95 | n=c->name_stack_size; 96 | if ((c->select_ptr-c->select_buffer+3+n) > 97 | c->select_size) { 98 | c->select_overflow=1; 99 | } else { 100 | ptr=c->select_ptr; 101 | c->select_hit=ptr; 102 | *ptr++=c->name_stack_size; 103 | *ptr++=zmin; 104 | *ptr++=zmax; 105 | for(i=0;iname_stack[i]; 106 | c->select_ptr=ptr; 107 | c->select_hits++; 108 | } 109 | } else { 110 | if (zminselect_hit[1]) c->select_hit[1]=zmin; 111 | if (zmax>c->select_hit[2]) c->select_hit[2]=zmax; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/specbuf.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | #include "msghandling.h" 3 | #include 4 | #include 5 | 6 | static void calc_buf(GLSpecBuf *buf, const float shininess) 7 | { 8 | int i; 9 | float val, inc; 10 | val = 0.0f; 11 | inc = 1.0f/SPECULAR_BUFFER_SIZE; 12 | for (i = 0; i <= SPECULAR_BUFFER_SIZE; i++) { 13 | buf->buf[i] = pow(val, shininess); 14 | val += inc; 15 | } 16 | } 17 | 18 | GLSpecBuf * 19 | specbuf_get_buffer(GLContext *c, const int shininess_i, 20 | const float shininess) 21 | { 22 | GLSpecBuf *found, *oldest; 23 | found = oldest = c->specbuf_first; 24 | while (found && found->shininess_i != shininess_i) { 25 | if (found->last_used < oldest->last_used) { 26 | oldest = found; 27 | } 28 | found = found->next; 29 | } 30 | if (found) { /* hey, found one! */ 31 | found->last_used = c->specbuf_used_counter++; 32 | return found; 33 | } 34 | if (oldest == NULL || c->specbuf_num_buffers < MAX_SPECULAR_BUFFERS) { 35 | /* create new buffer */ 36 | GLSpecBuf *buf = gl_malloc(sizeof(GLSpecBuf)); 37 | if (!buf) gl_fatal_error("could not allocate specular buffer"); 38 | c->specbuf_num_buffers++; 39 | buf->next = c->specbuf_first; 40 | c->specbuf_first = buf; 41 | buf->last_used = c->specbuf_used_counter++; 42 | buf->shininess_i = shininess_i; 43 | calc_buf(buf, shininess); 44 | return buf; 45 | } 46 | /* overwrite the lru buffer */ 47 | /*tgl_trace("overwriting spec buffer :(\n");*/ 48 | oldest->shininess_i = shininess_i; 49 | oldest->last_used = c->specbuf_used_counter++; 50 | calc_buf(oldest, shininess); 51 | return oldest; 52 | } 53 | -------------------------------------------------------------------------------- /src/specbuf.h: -------------------------------------------------------------------------------- 1 | #ifndef _tgl_specbuf_h_ 2 | #define _tgl_specbuf_h_ 3 | 4 | /* Max # of specular light pow buffers */ 5 | #define MAX_SPECULAR_BUFFERS 8 6 | /* # of entries in specular buffer */ 7 | #define SPECULAR_BUFFER_SIZE 1024 8 | /* specular buffer granularity */ 9 | #define SPECULAR_BUFFER_RESOLUTION 1024 10 | 11 | typedef struct GLSpecBuf { 12 | int shininess_i; 13 | int last_used; 14 | float buf[SPECULAR_BUFFER_SIZE+1]; 15 | struct GLSpecBuf *next; 16 | } GLSpecBuf; 17 | 18 | GLSpecBuf *specbuf_get_buffer(GLContext *c, const int shininess_i, 19 | const float shininess); 20 | void specbuf_cleanup(GLContext *c); /* free all memory used */ 21 | 22 | #endif /* _tgl_specbuf_h_ */ -------------------------------------------------------------------------------- /src/texture.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Texture Manager 3 | */ 4 | 5 | #include "zgl.h" 6 | 7 | static GLTexture *find_texture(GLContext *c,int h) 8 | { 9 | GLTexture *t; 10 | 11 | t=c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE]; 12 | while (t!=NULL) { 13 | if (t->handle == h) return t; 14 | t=t->next; 15 | } 16 | return NULL; 17 | } 18 | 19 | static void free_texture(GLContext *c,int h) 20 | { 21 | GLTexture *t,**ht; 22 | GLImage *im; 23 | int i; 24 | 25 | t=find_texture(c,h); 26 | if (t->prev==NULL) { 27 | ht=&c->shared_state.texture_hash_table 28 | [t->handle % TEXTURE_HASH_TABLE_SIZE]; 29 | *ht=t->next; 30 | } else { 31 | t->prev->next=t->next; 32 | } 33 | if (t->next!=NULL) t->next->prev=t->prev; 34 | 35 | for(i=0;iimages[i]; 37 | if (im->pixmap != NULL) gl_free(im->pixmap); 38 | } 39 | 40 | gl_free(t); 41 | } 42 | 43 | GLTexture *alloc_texture(GLContext *c,int h) 44 | { 45 | GLTexture *t,**ht; 46 | 47 | t=gl_zalloc(sizeof(GLTexture)); 48 | 49 | ht=&c->shared_state.texture_hash_table[h % TEXTURE_HASH_TABLE_SIZE]; 50 | 51 | t->next=*ht; 52 | t->prev=NULL; 53 | if (t->next != NULL) t->next->prev=t; 54 | *ht=t; 55 | 56 | t->handle=h; 57 | 58 | return t; 59 | } 60 | 61 | 62 | void glInitTextures(GLContext *c) 63 | { 64 | /* textures */ 65 | 66 | c->texture_2d_enabled=0; 67 | c->current_texture=find_texture(c,0); 68 | } 69 | 70 | void glGenTextures(int n, unsigned int *textures) 71 | { 72 | GLContext *c=gl_get_context(); 73 | int max,i; 74 | GLTexture *t; 75 | 76 | max=0; 77 | for(i=0;ishared_state.texture_hash_table[i]; 79 | while (t!=NULL) { 80 | if (t->handle>max) max=t->handle; 81 | t=t->next; 82 | } 83 | 84 | } 85 | for(i=0;icurrent_texture) { 101 | glBindTexture(GL_TEXTURE_2D,0); 102 | } 103 | free_texture(c,textures[i]); 104 | } 105 | } 106 | } 107 | 108 | 109 | void glopBindTexture(GLContext *c,GLParam *p) 110 | { 111 | int target=p[1].i; 112 | int texture=p[2].i; 113 | GLTexture *t; 114 | 115 | assert(target == GL_TEXTURE_2D && texture >= 0); 116 | 117 | t=find_texture(c,texture); 118 | if (t==NULL) { 119 | t=alloc_texture(c,texture); 120 | } 121 | c->current_texture=t; 122 | } 123 | 124 | void glopTexImage2D(GLContext *c,GLParam *p) 125 | { 126 | int target=p[1].i; 127 | int level=p[2].i; 128 | int components=p[3].i; 129 | int width=p[4].i; 130 | int height=p[5].i; 131 | int border=p[6].i; 132 | int format=p[7].i; 133 | int type=p[8].i; 134 | void *pixels=p[9].p; 135 | GLImage *im; 136 | unsigned char *pixels1; 137 | int do_free; 138 | 139 | if (!(target == GL_TEXTURE_2D && level == 0 && components == 3 && 140 | border == 0 && format == GL_RGB && 141 | type == GL_UNSIGNED_BYTE)) { 142 | gl_fatal_error("glTexImage2D: combinaison of parameters not handled"); 143 | } 144 | 145 | do_free=0; 146 | if (width != 256 || height != 256) { 147 | pixels1 = gl_malloc(256 * 256 * 3); 148 | /* no interpolation is done here to respect the original image aliasing ! */ 149 | gl_resizeImageNoInterpolate(pixels1,256,256,pixels,width,height); 150 | do_free=1; 151 | width=256; 152 | height=256; 153 | } else { 154 | pixels1=pixels; 155 | } 156 | 157 | im=&c->current_texture->images[level]; 158 | im->xsize=width; 159 | im->ysize=height; 160 | if (im->pixmap!=NULL) gl_free(im->pixmap); 161 | #if TGL_FEATURE_RENDER_BITS == 24 162 | im->pixmap=gl_malloc(width*height*3); 163 | if(im->pixmap) { 164 | memcpy(im->pixmap,pixels1,width*height*3); 165 | } 166 | #elif TGL_FEATURE_RENDER_BITS == 32 167 | im->pixmap=gl_malloc(width*height*4); 168 | if(im->pixmap) { 169 | gl_convertRGB_to_8A8R8G8B(im->pixmap,pixels1,width,height); 170 | } 171 | #elif TGL_FEATURE_RENDER_BITS == 16 172 | im->pixmap=gl_malloc(width*height*2); 173 | if(im->pixmap) { 174 | gl_convertRGB_to_5R6G5B(im->pixmap,pixels1,width,height); 175 | } 176 | #else 177 | #error TODO 178 | #endif 179 | if (do_free) gl_free(pixels1); 180 | } 181 | 182 | 183 | /* TODO: not all tests are done */ 184 | void glopTexEnv(GLContext *c,GLParam *p) 185 | { 186 | int target=p[1].i; 187 | int pname=p[2].i; 188 | int param=p[3].i; 189 | 190 | if (target != GL_TEXTURE_ENV) { 191 | error: 192 | gl_fatal_error("glTexParameter: unsupported option"); 193 | } 194 | 195 | if (pname != GL_TEXTURE_ENV_MODE) goto error; 196 | 197 | if (param != GL_DECAL) goto error; 198 | } 199 | 200 | /* TODO: not all tests are done */ 201 | void glopTexParameter(GLContext *c,GLParam *p) 202 | { 203 | int target=p[1].i; 204 | int pname=p[2].i; 205 | int param=p[3].i; 206 | 207 | if (target != GL_TEXTURE_2D) { 208 | error: 209 | gl_fatal_error("glTexParameter: unsupported option"); 210 | } 211 | 212 | switch(pname) { 213 | case GL_TEXTURE_WRAP_S: 214 | case GL_TEXTURE_WRAP_T: 215 | if (param != GL_REPEAT) goto error; 216 | break; 217 | } 218 | } 219 | 220 | void glopPixelStore(GLContext *c,GLParam *p) 221 | { 222 | int pname=p[1].i; 223 | int param=p[2].i; 224 | 225 | if (pname != GL_UNPACK_ALIGNMENT || 226 | param != 1) { 227 | gl_fatal_error("glPixelStore: unsupported option"); 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /src/vertex.c: -------------------------------------------------------------------------------- 1 | #include "zgl.h" 2 | #include "string.h" 3 | 4 | void glopNormal(GLContext * c, GLParam * p) 5 | { 6 | V3 v; 7 | 8 | v.X = p[1].f; 9 | v.Y = p[2].f; 10 | v.Z = p[3].f; 11 | 12 | c->current_normal.X = v.X; 13 | c->current_normal.Y = v.Y; 14 | c->current_normal.Z = v.Z; 15 | c->current_normal.W = 0; 16 | } 17 | 18 | void glopTexCoord(GLContext * c, GLParam * p) 19 | { 20 | c->current_tex_coord.X = p[1].f; 21 | c->current_tex_coord.Y = p[2].f; 22 | c->current_tex_coord.Z = p[3].f; 23 | c->current_tex_coord.W = p[4].f; 24 | } 25 | 26 | void glopEdgeFlag(GLContext * c, GLParam * p) 27 | { 28 | c->current_edge_flag = p[1].i; 29 | } 30 | 31 | void glopColor(GLContext * c, GLParam * p) 32 | { 33 | 34 | c->current_color.X = p[1].f; 35 | c->current_color.Y = p[2].f; 36 | c->current_color.Z = p[3].f; 37 | c->current_color.W = p[4].f; 38 | c->longcurrent_color[0] = p[5].ui; 39 | c->longcurrent_color[1] = p[6].ui; 40 | c->longcurrent_color[2] = p[7].ui; 41 | 42 | if (c->color_material_enabled) { 43 | GLParam q[7]; 44 | q[0].op = OP_Material; 45 | q[1].i = c->current_color_material_mode; 46 | q[2].i = c->current_color_material_type; 47 | q[3].f = p[1].f; 48 | q[4].f = p[2].f; 49 | q[5].f = p[3].f; 50 | q[6].f = p[4].f; 51 | glopMaterial(c, q); 52 | } 53 | } 54 | 55 | 56 | void gl_eval_viewport(GLContext * c) 57 | { 58 | GLViewport *v; 59 | float zsize = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS)); 60 | 61 | v = &c->viewport; 62 | 63 | v->trans.X = ((v->xsize - 0.5) / 2.0) + v->xmin; 64 | v->trans.Y = ((v->ysize - 0.5) / 2.0) + v->ymin; 65 | v->trans.Z = ((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2; 66 | 67 | v->scale.X = (v->xsize - 0.5) / 2.0; 68 | v->scale.Y = -(v->ysize - 0.5) / 2.0; 69 | v->scale.Z = -((zsize - 0.5) / 2.0); 70 | } 71 | 72 | void glopBegin(GLContext * c, GLParam * p) 73 | { 74 | int type; 75 | M4 tmp; 76 | 77 | assert(c->in_begin == 0); 78 | 79 | type = p[1].i; 80 | c->begin_type = type; 81 | c->in_begin = 1; 82 | c->vertex_n = 0; 83 | c->vertex_cnt = 0; 84 | 85 | if (c->matrix_model_projection_updated) { 86 | 87 | if (c->lighting_enabled) { 88 | /* precompute inverse modelview */ 89 | gl_M4_Inv(&tmp, c->matrix_stack_ptr[0]); 90 | gl_M4_Transpose(&c->matrix_model_view_inv, &tmp); 91 | } else { 92 | float *m = &c->matrix_model_projection.m[0][0]; 93 | /* precompute projection matrix */ 94 | gl_M4_Mul(&c->matrix_model_projection, 95 | c->matrix_stack_ptr[1], 96 | c->matrix_stack_ptr[0]); 97 | /* test to accelerate computation */ 98 | c->matrix_model_projection_no_w_transform = 0; 99 | if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) 100 | c->matrix_model_projection_no_w_transform = 1; 101 | } 102 | 103 | /* test if the texture matrix is not Identity */ 104 | c->apply_texture_matrix = !gl_M4_IsId(c->matrix_stack_ptr[2]); 105 | 106 | c->matrix_model_projection_updated = 0; 107 | } 108 | /* viewport */ 109 | if (c->viewport.updated) { 110 | gl_eval_viewport(c); 111 | c->viewport.updated = 0; 112 | } 113 | /* triangle drawing functions */ 114 | if (c->render_mode == GL_SELECT) { 115 | c->draw_triangle_front = gl_draw_triangle_select; 116 | c->draw_triangle_back = gl_draw_triangle_select; 117 | } else { 118 | switch (c->polygon_mode_front) { 119 | case GL_POINT: 120 | c->draw_triangle_front = gl_draw_triangle_point; 121 | break; 122 | case GL_LINE: 123 | c->draw_triangle_front = gl_draw_triangle_line; 124 | break; 125 | default: 126 | c->draw_triangle_front = gl_draw_triangle_fill; 127 | break; 128 | } 129 | 130 | switch (c->polygon_mode_back) { 131 | case GL_POINT: 132 | c->draw_triangle_back = gl_draw_triangle_point; 133 | break; 134 | case GL_LINE: 135 | c->draw_triangle_back = gl_draw_triangle_line; 136 | break; 137 | default: 138 | c->draw_triangle_back = gl_draw_triangle_fill; 139 | break; 140 | } 141 | } 142 | } 143 | 144 | /* coords, tranformation , clip code and projection */ 145 | /* TODO : handle all cases */ 146 | static inline void gl_vertex_transform(GLContext * c, GLVertex * v) 147 | { 148 | float *m; 149 | V4 *n; 150 | 151 | if (c->lighting_enabled) { 152 | /* eye coordinates needed for lighting */ 153 | 154 | m = &c->matrix_stack_ptr[0]->m[0][0]; 155 | v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] + 156 | v->coord.Z * m[2] + m[3]); 157 | v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + 158 | v->coord.Z * m[6] + m[7]); 159 | v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + 160 | v->coord.Z * m[10] + m[11]); 161 | v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] + 162 | v->coord.Z * m[14] + m[15]); 163 | 164 | /* projection coordinates */ 165 | m = &c->matrix_stack_ptr[1]->m[0][0]; 166 | v->pc.X = (v->ec.X * m[0] + v->ec.Y * m[1] + 167 | v->ec.Z * m[2] + v->ec.W * m[3]); 168 | v->pc.Y = (v->ec.X * m[4] + v->ec.Y * m[5] + 169 | v->ec.Z * m[6] + v->ec.W * m[7]); 170 | v->pc.Z = (v->ec.X * m[8] + v->ec.Y * m[9] + 171 | v->ec.Z * m[10] + v->ec.W * m[11]); 172 | v->pc.W = (v->ec.X * m[12] + v->ec.Y * m[13] + 173 | v->ec.Z * m[14] + v->ec.W * m[15]); 174 | 175 | m = &c->matrix_model_view_inv.m[0][0]; 176 | n = &c->current_normal; 177 | 178 | v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]); 179 | v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]); 180 | v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]); 181 | 182 | if (c->normalize_enabled) { 183 | gl_V3_Norm(&v->normal); 184 | } 185 | } else { 186 | /* no eye coordinates needed, no normal */ 187 | /* NOTE: W = 1 is assumed */ 188 | m = &c->matrix_model_projection.m[0][0]; 189 | 190 | v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] + 191 | v->coord.Z * m[2] + m[3]); 192 | v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + 193 | v->coord.Z * m[6] + m[7]); 194 | v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + 195 | v->coord.Z * m[10] + m[11]); 196 | if (c->matrix_model_projection_no_w_transform) { 197 | v->pc.W = m[15]; 198 | } else { 199 | v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] + 200 | v->coord.Z * m[14] + m[15]); 201 | } 202 | } 203 | 204 | v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W); 205 | } 206 | 207 | void glopVertex(GLContext * c, GLParam * p) 208 | { 209 | GLVertex *v; 210 | int n, i, cnt; 211 | 212 | assert(c->in_begin != 0); 213 | 214 | n = c->vertex_n; 215 | cnt = c->vertex_cnt; 216 | cnt++; 217 | c->vertex_cnt = cnt; 218 | 219 | /* quick fix to avoid crashes on large polygons */ 220 | if (n >= c->vertex_max) { 221 | GLVertex *newarray; 222 | c->vertex_max <<= 1; /* just double size */ 223 | newarray = gl_malloc(sizeof(GLVertex) * c->vertex_max); 224 | if (!newarray) { 225 | gl_fatal_error("unable to allocate GLVertex array.\n"); 226 | } 227 | memcpy(newarray, c->vertex, n * sizeof(GLVertex)); 228 | gl_free(c->vertex); 229 | c->vertex = newarray; 230 | } 231 | /* new vertex entry */ 232 | v = &c->vertex[n]; 233 | n++; 234 | 235 | v->coord.X = p[1].f; 236 | v->coord.Y = p[2].f; 237 | v->coord.Z = p[3].f; 238 | v->coord.W = p[4].f; 239 | 240 | gl_vertex_transform(c, v); 241 | 242 | /* color */ 243 | 244 | if (c->lighting_enabled) { 245 | gl_shade_vertex(c, v); 246 | } else { 247 | v->color = c->current_color; 248 | } 249 | 250 | /* tex coords */ 251 | 252 | if (c->texture_2d_enabled) { 253 | if (c->apply_texture_matrix) { 254 | gl_M4_MulV4(&v->tex_coord, c->matrix_stack_ptr[2], &c->current_tex_coord); 255 | } else { 256 | v->tex_coord = c->current_tex_coord; 257 | } 258 | } 259 | /* precompute the mapping to the viewport */ 260 | if (v->clip_code == 0) 261 | gl_transform_to_viewport(c, v); 262 | 263 | /* edge flag */ 264 | 265 | v->edge_flag = c->current_edge_flag; 266 | 267 | switch (c->begin_type) { 268 | case GL_POINTS: 269 | gl_draw_point(c, &c->vertex[0]); 270 | n = 0; 271 | break; 272 | 273 | case GL_LINES: 274 | if (n == 2) { 275 | gl_draw_line(c, &c->vertex[0], &c->vertex[1]); 276 | n = 0; 277 | } 278 | break; 279 | case GL_LINE_STRIP: 280 | case GL_LINE_LOOP: 281 | if (n == 1) { 282 | c->vertex[2] = c->vertex[0]; 283 | } else if (n == 2) { 284 | gl_draw_line(c, &c->vertex[0], &c->vertex[1]); 285 | c->vertex[0] = c->vertex[1]; 286 | n = 1; 287 | } 288 | break; 289 | 290 | case GL_TRIANGLES: 291 | if (n == 3) { 292 | gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); 293 | n = 0; 294 | } 295 | break; 296 | case GL_TRIANGLE_STRIP: 297 | if (cnt >= 3) { 298 | if (n == 3) 299 | n = 0; 300 | /* needed to respect triangle orientation */ 301 | switch(cnt & 1) { 302 | case 0: 303 | gl_draw_triangle(c,&c->vertex[2],&c->vertex[1],&c->vertex[0]); 304 | break; 305 | default: 306 | case 1: 307 | gl_draw_triangle(c,&c->vertex[0],&c->vertex[1],&c->vertex[2]); 308 | break; 309 | } 310 | } 311 | break; 312 | case GL_TRIANGLE_FAN: 313 | if (n == 3) { 314 | gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); 315 | c->vertex[1] = c->vertex[2]; 316 | n = 2; 317 | } 318 | break; 319 | 320 | case GL_QUADS: 321 | if (n == 4) { 322 | c->vertex[2].edge_flag = 0; 323 | gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); 324 | c->vertex[2].edge_flag = 1; 325 | c->vertex[0].edge_flag = 0; 326 | gl_draw_triangle(c, &c->vertex[0], &c->vertex[2], &c->vertex[3]); 327 | n = 0; 328 | } 329 | break; 330 | 331 | case GL_QUAD_STRIP: 332 | if (n == 4) { 333 | gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]); 334 | gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]); 335 | for (i = 0; i < 2; i++) 336 | c->vertex[i] = c->vertex[i + 2]; 337 | n = 2; 338 | } 339 | break; 340 | case GL_POLYGON: 341 | break; 342 | default: 343 | gl_fatal_error("glBegin: type %x not handled\n", c->begin_type); 344 | } 345 | 346 | c->vertex_n = n; 347 | } 348 | 349 | void glopEnd(GLContext * c, GLParam * param) 350 | { 351 | assert(c->in_begin == 1); 352 | 353 | if (c->begin_type == GL_LINE_LOOP) { 354 | if (c->vertex_cnt >= 3) { 355 | gl_draw_line(c, &c->vertex[0], &c->vertex[2]); 356 | } 357 | } else if (c->begin_type == GL_POLYGON) { 358 | int i = c->vertex_cnt; 359 | while (i >= 3) { 360 | i--; 361 | gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]); 362 | } 363 | } 364 | c->in_begin = 0; 365 | } 366 | -------------------------------------------------------------------------------- /src/zbuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | * Z buffer: 16 bits Z / 16 bits color 4 | * 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "zbuffer.h" 11 | 12 | ZBuffer *ZB_open(int xsize, int ysize, int mode, 13 | int nb_colors, 14 | unsigned char *color_indexes, 15 | int *color_table, 16 | void *frame_buffer) 17 | { 18 | ZBuffer *zb; 19 | int size; 20 | 21 | zb = gl_malloc(sizeof(ZBuffer)); 22 | if (zb == NULL) 23 | return NULL; 24 | 25 | zb->xsize = xsize; 26 | zb->ysize = ysize; 27 | zb->mode = mode; 28 | zb->linesize = (xsize * PSZB + 3) & ~3; 29 | 30 | switch (mode) { 31 | #ifdef TGL_FEATURE_8_BITS 32 | case ZB_MODE_INDEX: 33 | ZB_initDither(zb, nb_colors, color_indexes, color_table); 34 | break; 35 | #endif 36 | #ifdef TGL_FEATURE_32_BITS 37 | case ZB_MODE_RGBA: 38 | #endif 39 | #ifdef TGL_FEATURE_24_BITS 40 | case ZB_MODE_RGB24: 41 | #endif 42 | case ZB_MODE_5R6G5B: 43 | zb->nb_colors = 0; 44 | break; 45 | default: 46 | goto error; 47 | } 48 | 49 | size = zb->xsize * zb->ysize * sizeof(unsigned short); 50 | 51 | zb->zbuf = gl_malloc(size); 52 | if (zb->zbuf == NULL) 53 | goto error; 54 | 55 | if (frame_buffer == NULL) { 56 | zb->pbuf = gl_malloc(zb->ysize * zb->linesize); 57 | if (zb->pbuf == NULL) { 58 | gl_free(zb->zbuf); 59 | goto error; 60 | } 61 | zb->frame_buffer_allocated = 1; 62 | } else { 63 | zb->frame_buffer_allocated = 0; 64 | zb->pbuf = frame_buffer; 65 | } 66 | 67 | zb->current_texture = NULL; 68 | 69 | return zb; 70 | error: 71 | gl_free(zb); 72 | return NULL; 73 | } 74 | 75 | void ZB_close(ZBuffer * zb) 76 | { 77 | #ifdef TGL_FEATURE_8_BITS 78 | if (zb->mode == ZB_MODE_INDEX) 79 | ZB_closeDither(zb); 80 | #endif 81 | 82 | if (zb->frame_buffer_allocated) 83 | gl_free(zb->pbuf); 84 | 85 | gl_free(zb->zbuf); 86 | gl_free(zb); 87 | } 88 | 89 | void ZB_resize(ZBuffer * zb, void *frame_buffer, int xsize, int ysize) 90 | { 91 | int size; 92 | 93 | /* xsize must be a multiple of 4 */ 94 | xsize = xsize & ~3; 95 | 96 | zb->xsize = xsize; 97 | zb->ysize = ysize; 98 | zb->linesize = (xsize * PSZB + 3) & ~3; 99 | 100 | size = zb->xsize * zb->ysize * sizeof(unsigned short); 101 | 102 | gl_free(zb->zbuf); 103 | zb->zbuf = gl_malloc(size); 104 | 105 | if (zb->frame_buffer_allocated) 106 | gl_free(zb->pbuf); 107 | 108 | if (frame_buffer == NULL) { 109 | zb->pbuf = gl_malloc(zb->ysize * zb->linesize); 110 | zb->frame_buffer_allocated = 1; 111 | } else { 112 | zb->pbuf = frame_buffer; 113 | zb->frame_buffer_allocated = 0; 114 | } 115 | } 116 | 117 | static void ZB_copyBuffer(ZBuffer * zb, 118 | void *buf, 119 | int linesize) 120 | { 121 | unsigned char *p1; 122 | PIXEL *q; 123 | int y, n; 124 | 125 | q = zb->pbuf; 126 | p1 = buf; 127 | n = zb->xsize * PSZB; 128 | for (y = 0; y < zb->ysize; y++) { 129 | memcpy(p1, q, n); 130 | p1 += linesize; 131 | q = (PIXEL *) ((char *) q + zb->linesize); 132 | } 133 | } 134 | 135 | #if TGL_FEATURE_RENDER_BITS == 16 136 | 137 | /* 32 bpp copy */ 138 | 139 | #ifdef TGL_FEATURE_32_BITS 140 | 141 | #define RGB16_TO_RGB32(p0,p1,v)\ 142 | {\ 143 | unsigned int g,b,gb;\ 144 | g = (v & 0x07E007E0) << 5;\ 145 | b = (v & 0x001F001F) << 3;\ 146 | gb = g | b;\ 147 | p0 = (gb & 0x0000FFFF) | ((v & 0x0000F800) << 8);\ 148 | p1 = (gb >> 16) | ((v & 0xF8000000) >> 8);\ 149 | } 150 | 151 | static void ZB_copyFrameBufferRGB32(ZBuffer * zb, 152 | void *buf, 153 | int linesize) 154 | { 155 | unsigned short *q; 156 | unsigned int *p, *p1, v, w0, w1; 157 | int y, n; 158 | 159 | q = zb->pbuf; 160 | p1 = (unsigned int *) buf; 161 | 162 | for (y = 0; y < zb->ysize; y++) { 163 | p = p1; 164 | n = zb->xsize >> 2; 165 | do { 166 | v = *(unsigned int *) q; 167 | #if BYTE_ORDER == BIG_ENDIAN 168 | RGB16_TO_RGB32(w1, w0, v); 169 | #else 170 | RGB16_TO_RGB32(w0, w1, v); 171 | #endif 172 | p[0] = w0; 173 | p[1] = w1; 174 | 175 | v = *(unsigned int *) (q + 2); 176 | #if BYTE_ORDER == BIG_ENDIAN 177 | RGB16_TO_RGB32(w1, w0, v); 178 | #else 179 | RGB16_TO_RGB32(w0, w1, v); 180 | #endif 181 | p[2] = w0; 182 | p[3] = w1; 183 | 184 | q += 4; 185 | p += 4; 186 | } while (--n > 0); 187 | 188 | p1 += linesize; 189 | } 190 | } 191 | 192 | #endif 193 | 194 | /* 24 bit packed pixel handling */ 195 | 196 | #ifdef TGL_FEATURE_24_BITS 197 | 198 | /* order: RGBR GBRG BRGB */ 199 | 200 | /* XXX: packed pixel 24 bit support not tested */ 201 | /* XXX: big endian case not optimised */ 202 | 203 | #if BYTE_ORDER == BIG_ENDIAN 204 | 205 | #define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ 206 | {\ 207 | unsigned int r1,g1,b1,gb1,g2,b2,gb2;\ 208 | v1 = (v1 << 16) | (v1 >> 16);\ 209 | v2 = (v2 << 16) | (v2 >> 16);\ 210 | r1 = (v1 & 0xF800F800);\ 211 | g1 = (v1 & 0x07E007E0) << 5;\ 212 | b1 = (v1 & 0x001F001F) << 3;\ 213 | gb1 = g1 | b1;\ 214 | p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ 215 | g2 = (v2 & 0x07E007E0) << 5;\ 216 | b2 = (v2 & 0x001F001F) << 3;\ 217 | gb2 = g2 | b2;\ 218 | p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ 219 | p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ 220 | } 221 | 222 | #else 223 | 224 | #define RGB16_TO_RGB24(p0,p1,p2,v1,v2)\ 225 | {\ 226 | unsigned int r1,g1,b1,gb1,g2,b2,gb2;\ 227 | r1 = (v1 & 0xF800F800);\ 228 | g1 = (v1 & 0x07E007E0) << 5;\ 229 | b1 = (v1 & 0x001F001F) << 3;\ 230 | gb1 = g1 | b1;\ 231 | p0 = ((gb1 & 0x0000FFFF) << 8) | (r1 << 16) | (r1 >> 24);\ 232 | g2 = (v2 & 0x07E007E0) << 5;\ 233 | b2 = (v2 & 0x001F001F) << 3;\ 234 | gb2 = g2 | b2;\ 235 | p1 = (gb1 & 0xFFFF0000) | (v2 & 0xF800) | ((gb2 >> 8) & 0xff);\ 236 | p2 = (gb2 << 24) | ((v2 & 0xF8000000) >> 8) | (gb2 >> 16);\ 237 | } 238 | 239 | #endif 240 | 241 | static void ZB_copyFrameBufferRGB24(ZBuffer * zb, 242 | void *buf, 243 | int linesize) 244 | { 245 | unsigned short *q; 246 | unsigned int *p, w0, w1, w2, v0, v1; 247 | char *p1; 248 | int y, n; 249 | 250 | q = zb->pbuf; 251 | p1 = buf; 252 | linesize = linesize * 3; 253 | 254 | for (y = 0; y < zb->ysize; y++) { 255 | p = (unsigned int *)p1; 256 | n = zb->xsize >> 2; 257 | do { 258 | v0 = *(unsigned int *) q; 259 | v1 = *(unsigned int *) (q + 2); 260 | RGB16_TO_RGB24(w0, w1, w2, v0, v1); 261 | p[0] = w0; 262 | p[1] = w1; 263 | p[2] = w2; 264 | 265 | q += 4; 266 | p += 3; 267 | } while (--n > 0); 268 | p1 += linesize; 269 | } 270 | } 271 | 272 | #endif 273 | 274 | void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, 275 | int linesize) 276 | { 277 | switch (zb->mode) { 278 | #ifdef TGL_FEATURE_8_BITS 279 | case ZB_MODE_INDEX: 280 | ZB_ditherFrameBuffer(zb, buf, linesize >> 1); 281 | break; 282 | #endif 283 | #ifdef TGL_FEATURE_16_BITS 284 | case ZB_MODE_5R6G5B: 285 | ZB_copyBuffer(zb, buf, linesize); 286 | break; 287 | #endif 288 | #ifdef TGL_FEATURE_32_BITS 289 | case ZB_MODE_RGBA: 290 | ZB_copyFrameBufferRGB32(zb, buf, linesize >> 1); 291 | break; 292 | #endif 293 | #ifdef TGL_FEATURE_24_BITS 294 | case ZB_MODE_RGB24: 295 | ZB_copyFrameBufferRGB24(zb, buf, linesize >> 1); 296 | break; 297 | #endif 298 | default: 299 | assert(0); 300 | } 301 | } 302 | 303 | #endif /* TGL_FEATURE_RENDER_BITS == 16 */ 304 | 305 | #if TGL_FEATURE_RENDER_BITS == 24 306 | 307 | #define RGB24_TO_RGB16(r, g, b) \ 308 | ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) 309 | 310 | /* XXX: not optimized */ 311 | static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb, 312 | void *buf, int linesize) 313 | { 314 | PIXEL *q; 315 | unsigned short *p, *p1; 316 | int y, n; 317 | 318 | q = zb->pbuf; 319 | p1 = (unsigned short *) buf; 320 | 321 | for (y = 0; y < zb->ysize; y++) { 322 | p = p1; 323 | n = zb->xsize >> 2; 324 | do { 325 | p[0] = RGB24_TO_RGB16(q[0], q[1], q[2]); 326 | p[1] = RGB24_TO_RGB16(q[3], q[4], q[5]); 327 | p[2] = RGB24_TO_RGB16(q[6], q[7], q[8]); 328 | p[3] = RGB24_TO_RGB16(q[9], q[10], q[11]); 329 | q = (PIXEL *)((char *)q + 4 * PSZB); 330 | p += 4; 331 | } while (--n > 0); 332 | p1 = (unsigned short *)((char *)p1 + linesize); 333 | } 334 | } 335 | 336 | void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, 337 | int linesize) 338 | { 339 | switch (zb->mode) { 340 | #ifdef TGL_FEATURE_16_BITS 341 | case ZB_MODE_5R6G5B: 342 | ZB_copyFrameBuffer5R6G5B(zb, buf, linesize); 343 | break; 344 | #endif 345 | #ifdef TGL_FEATURE_24_BITS 346 | case ZB_MODE_RGB24: 347 | ZB_copyBuffer(zb, buf, linesize); 348 | break; 349 | #endif 350 | default: 351 | assert(0); 352 | } 353 | } 354 | 355 | #endif /* TGL_FEATURE_RENDER_BITS == 24 */ 356 | 357 | #if TGL_FEATURE_RENDER_BITS == 32 358 | 359 | #define RGB32_TO_RGB16(v) \ 360 | (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3)) 361 | 362 | /* XXX: not optimized */ 363 | static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb, 364 | void *buf, int linesize) 365 | { 366 | PIXEL *q; 367 | unsigned short *p, *p1; 368 | int y, n; 369 | 370 | q = zb->pbuf; 371 | p1 = (unsigned short *) buf; 372 | 373 | for (y = 0; y < zb->ysize; y++) { 374 | p = p1; 375 | n = zb->xsize >> 2; 376 | do { 377 | p[0] = RGB32_TO_RGB16(q[0]); 378 | p[1] = RGB32_TO_RGB16(q[1]); 379 | p[2] = RGB32_TO_RGB16(q[2]); 380 | p[3] = RGB32_TO_RGB16(q[3]); 381 | q += 4; 382 | p += 4; 383 | } while (--n > 0); 384 | p1 = (unsigned short *)((char *)p1 + linesize); 385 | } 386 | } 387 | 388 | void ZB_copyFrameBuffer(ZBuffer * zb, void *buf, 389 | int linesize) 390 | { 391 | switch (zb->mode) { 392 | #ifdef TGL_FEATURE_16_BITS 393 | case ZB_MODE_5R6G5B: 394 | ZB_copyFrameBuffer5R6G5B(zb, buf, linesize); 395 | break; 396 | #endif 397 | #ifdef TGL_FEATURE_32_BITS 398 | case ZB_MODE_RGBA: 399 | ZB_copyBuffer(zb, buf, linesize); 400 | break; 401 | #endif 402 | default: 403 | assert(0); 404 | } 405 | } 406 | 407 | #endif /* TGL_FEATURE_RENDER_BITS == 32 */ 408 | 409 | 410 | /* 411 | * adr must be aligned on an 'int' 412 | */ 413 | void memset_s(void *adr, int val, int count) 414 | { 415 | int i, n, v; 416 | unsigned int *p; 417 | unsigned short *q; 418 | 419 | p = adr; 420 | v = val | (val << 16); 421 | 422 | n = count >> 3; 423 | for (i = 0; i < n; i++) { 424 | p[0] = v; 425 | p[1] = v; 426 | p[2] = v; 427 | p[3] = v; 428 | p += 4; 429 | } 430 | 431 | q = (unsigned short *) p; 432 | n = count & 7; 433 | for (i = 0; i < n; i++) 434 | *q++ = val; 435 | } 436 | 437 | void memset_l(void *adr, int val, int count) 438 | { 439 | int i, n, v; 440 | unsigned int *p; 441 | 442 | p = adr; 443 | v = val; 444 | n = count >> 2; 445 | for (i = 0; i < n; i++) { 446 | p[0] = v; 447 | p[1] = v; 448 | p[2] = v; 449 | p[3] = v; 450 | p += 4; 451 | } 452 | 453 | n = count & 3; 454 | for (i = 0; i < n; i++) 455 | *p++ = val; 456 | } 457 | 458 | /* count must be a multiple of 4 and >= 4 */ 459 | void memset_RGB24(void *adr,int r, int v, int b,long count) 460 | { 461 | long i, n; 462 | register long v1,v2,v3,*pt=(long *)(adr); 463 | unsigned char *p,R=(unsigned char)r,V=(unsigned char)v,B=(unsigned char)b; 464 | 465 | p=(unsigned char *)adr; 466 | *p++=R; 467 | *p++=V; 468 | *p++=B; 469 | *p++=R; 470 | *p++=V; 471 | *p++=B; 472 | *p++=R; 473 | *p++=V; 474 | *p++=B; 475 | *p++=R; 476 | *p++=V; 477 | *p++=B; 478 | v1=*pt++; 479 | v2=*pt++; 480 | v3=*pt++; 481 | n = count >> 2; 482 | for(i=1;izbuf, z, zb->xsize * zb->ysize); 500 | } 501 | if (clear_color) { 502 | pp = zb->pbuf; 503 | for (y = 0; y < zb->ysize; y++) { 504 | #if TGL_FEATURE_RENDER_BITS == 15 || TGL_FEATURE_RENDER_BITS == 16 505 | color = RGB_TO_PIXEL(r, g, b); 506 | memset_s(pp, color, zb->xsize); 507 | #elif TGL_FEATURE_RENDER_BITS == 32 508 | color = RGB_TO_PIXEL(r, g, b); 509 | memset_l(pp, color, zb->xsize); 510 | #elif TGL_FEATURE_RENDER_BITS == 24 511 | memset_RGB24(pp,r>>8,g>>8,b>>8,zb->xsize); 512 | #else 513 | #error TODO 514 | #endif 515 | pp = (PIXEL *) ((char *) pp + zb->linesize); 516 | } 517 | } 518 | } 519 | -------------------------------------------------------------------------------- /src/zdither.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Highly optimised dithering 16 bits -> 8 bits. 3 | * The formulas were taken in Mesa (Bob Mercier mercier@hollywood.cinenet.net). 4 | */ 5 | 6 | #include 7 | #include 8 | #include "zbuffer.h" 9 | #include 10 | 11 | #if defined(TGL_FEATURE_8_BITS) 12 | 13 | #define _R 5 14 | #define _G 9 15 | #define _B 5 16 | #define _DX 4 17 | #define _DY 4 18 | #define _D (_DX*_DY) 19 | #define _MIX(r,g,b) ( ((g)<<6) | ((b)<<3) | (r) ) 20 | 21 | #define DITHER_TABLE_SIZE (1 << 15) 22 | 23 | #define DITHER_INDEX(r,g,b) ((b) + (g) * _B + (r) * (_B * _G)) 24 | 25 | #define MAXC 256 26 | static int kernel8[_DY*_DX] = { 27 | 0 * MAXC, 8 * MAXC, 2 * MAXC, 10 * MAXC, 28 | 12 * MAXC, 4 * MAXC, 14 * MAXC, 6 * MAXC, 29 | 3 * MAXC, 11 * MAXC, 1 * MAXC, 9 * MAXC, 30 | 15 * MAXC, 7 * MAXC, 13 * MAXC, 5 * MAXC, 31 | }; 32 | 33 | /* we build the color table and the lookup table */ 34 | 35 | void ZB_initDither(ZBuffer *zb,int nb_colors, 36 | unsigned char *color_indexes,int *color_table) 37 | { 38 | int c,r,g,b,i,index,r1,g1,b1; 39 | 40 | if (nb_colors < (_R * _G * _B)) { 41 | fprintf(stderr,"zdither: not enough colors\n"); 42 | exit(1); 43 | } 44 | 45 | for(i=0;inb_colors=nb_colors; 48 | zb->ctable=gl_malloc(nb_colors * sizeof(int)); 49 | 50 | for (r = 0; r < _R; r++) { 51 | for (g = 0; g < _G; g++) { 52 | for (b = 0; b < _B; b++) { 53 | r1=(r*255) / (_R - 1); 54 | g1=(g*255) / (_G - 1); 55 | b1=(b*255) / (_B - 1); 56 | index=DITHER_INDEX(r,g,b); 57 | c=(r1 << 16) | (g1 << 8) | b1; 58 | zb->ctable[index]=c; 59 | color_table[index]=c; 60 | } 61 | } 62 | } 63 | 64 | zb->dctable=gl_malloc( DITHER_TABLE_SIZE ); 65 | 66 | for(i=0;i> 12) & 0x7; 68 | g=(i >> 8) & 0xF; 69 | b=(i >> 3) & 0x7; 70 | index=DITHER_INDEX(r,g,b); 71 | zb->dctable[i]=color_indexes[index]; 72 | } 73 | } 74 | 75 | void ZB_closeDither(ZBuffer *zb) 76 | { 77 | gl_free(zb->ctable); 78 | gl_free(zb->dctable); 79 | } 80 | 81 | #if 0 82 | int ZDither_lookupColor(int r,int g,int b) 83 | { 84 | unsigned char *ctable=zdither_color_table; 85 | return ctable[_MIX(_DITH0(_R, r), _DITH0(_G, g),_DITH0(_B, b))]; 86 | } 87 | #endif 88 | 89 | 90 | #define DITHER_PIXEL2(a) \ 91 | { \ 92 | register int v,t,r,g,c; \ 93 | v=*(unsigned int *)(pp+(a)); \ 94 | g=(v & 0x07DF07DF) + g_d; \ 95 | r=(((v & 0xF800F800) >> 2) + r_d) & 0x70007000; \ 96 | t=r | g; \ 97 | c=ctable[t & 0xFFFF] | (ctable[t >> 16] << 8); \ 98 | *(unsigned short *)(dest+(a))=c; \ 99 | } 100 | 101 | /* NOTE: all the memory access are 16 bit aligned, so if buf or 102 | linesize are not multiple of 2, it cannot work efficiently (or 103 | hang!) */ 104 | 105 | void ZB_ditherFrameBuffer(ZBuffer *zb,unsigned char *buf, 106 | int linesize) 107 | { 108 | int xk,yk,x,y,c1,c2; 109 | unsigned char *dest1; 110 | unsigned short *pp1; 111 | int r_d,g_d,b_d; 112 | unsigned char *ctable=zb->dctable; 113 | register unsigned char *dest; 114 | register unsigned short *pp; 115 | 116 | assert( ((long)buf & 1) == 0 && (linesize & 1) == 0); 117 | 118 | for(yk=0;yk<4;yk++) { 119 | for(xk=0;xk<4;xk+=2) { 120 | #if BYTE_ORDER == BIG_ENDIAN 121 | c1=kernel8[yk*4+xk+1]; 122 | c2=kernel8[yk*4+xk]; 123 | #else 124 | c1=kernel8[yk*4+xk]; 125 | c2=kernel8[yk*4+xk+1]; 126 | #endif 127 | r_d=((c1 << 2) & 0xF800) >> 2; 128 | g_d=(c1 >> 4) & 0x07C0; 129 | b_d=(c1 >> 9) & 0x001F; 130 | 131 | r_d|=(((c2 << 2) & 0xF800) >> 2) << 16; 132 | g_d|=((c2 >> 4) & 0x07C0) << 16; 133 | b_d|=((c2 >> 9) & 0x001F) << 16; 134 | g_d=b_d | g_d; 135 | 136 | dest1=buf + (yk * linesize) + xk; 137 | pp1=zb->pbuf + (yk * zb->xsize) + xk; 138 | 139 | for(y=yk;yysize;y+=4) { 140 | dest=dest1; 141 | pp=pp1; 142 | for(x=xk;xxsize;x+=16) { 143 | 144 | DITHER_PIXEL2(0); 145 | DITHER_PIXEL2(1*4); 146 | DITHER_PIXEL2(2*4); 147 | DITHER_PIXEL2(3*4); 148 | 149 | pp+=16; 150 | dest+=16; 151 | } 152 | dest1+=linesize*4; 153 | pp1+=zb->xsize*4; 154 | } 155 | } 156 | } 157 | } 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /src/zgl.h: -------------------------------------------------------------------------------- 1 | #ifndef _tgl_zgl_h_ 2 | #define _tgl_zgl_h_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "zbuffer.h" 10 | #include "zmath.h" 11 | #include "zfeatures.h" 12 | 13 | #define DEBUG 14 | /* #define NDEBUG */ 15 | 16 | enum { 17 | 18 | #define ADD_OP(a,b,c) OP_ ## a , 19 | 20 | #include "opinfo.h" 21 | 22 | }; 23 | 24 | /* initially # of allocated GLVertexes (will grow when necessary) */ 25 | #define POLYGON_MAX_VERTEX 16 26 | 27 | /* Max # of specular light pow buffers */ 28 | #define MAX_SPECULAR_BUFFERS 8 29 | /* # of entries in specular buffer */ 30 | #define SPECULAR_BUFFER_SIZE 1024 31 | /* specular buffer granularity */ 32 | #define SPECULAR_BUFFER_RESOLUTION 1024 33 | 34 | 35 | #define MAX_MODELVIEW_STACK_DEPTH 32 36 | #define MAX_PROJECTION_STACK_DEPTH 8 37 | #define MAX_TEXTURE_STACK_DEPTH 8 38 | #define MAX_NAME_STACK_DEPTH 64 39 | #define MAX_TEXTURE_LEVELS 11 40 | #define MAX_LIGHTS 16 41 | 42 | #define VERTEX_HASH_SIZE 1031 43 | 44 | #define MAX_DISPLAY_LISTS 1024 45 | #define OP_BUFFER_MAX_SIZE 512 46 | 47 | #define TGL_OFFSET_FILL 0x1 48 | #define TGL_OFFSET_LINE 0x2 49 | #define TGL_OFFSET_POINT 0x4 50 | 51 | typedef struct GLSpecBuf { 52 | int shininess_i; 53 | int last_used; 54 | float buf[SPECULAR_BUFFER_SIZE+1]; 55 | struct GLSpecBuf *next; 56 | } GLSpecBuf; 57 | 58 | typedef struct GLLight { 59 | V4 ambient; 60 | V4 diffuse; 61 | V4 specular; 62 | V4 position; 63 | V3 spot_direction; 64 | float spot_exponent; 65 | float spot_cutoff; 66 | float attenuation[3]; 67 | /* precomputed values */ 68 | float cos_spot_cutoff; 69 | V3 norm_spot_direction; 70 | V3 norm_position; 71 | /* we use a linked list to know which are the enabled lights */ 72 | int enabled; 73 | struct GLLight *next,*prev; 74 | } GLLight; 75 | 76 | typedef struct GLMaterial { 77 | V4 emission; 78 | V4 ambient; 79 | V4 diffuse; 80 | V4 specular; 81 | float shininess; 82 | 83 | /* computed values */ 84 | int shininess_i; 85 | int do_specular; 86 | } GLMaterial; 87 | 88 | 89 | typedef struct GLViewport { 90 | int xmin,ymin,xsize,ysize; 91 | V3 scale; 92 | V3 trans; 93 | int updated; 94 | } GLViewport; 95 | 96 | typedef union { 97 | int op; 98 | float f; 99 | int i; 100 | unsigned int ui; 101 | void *p; 102 | } GLParam; 103 | 104 | typedef struct GLParamBuffer { 105 | GLParam ops[OP_BUFFER_MAX_SIZE]; 106 | struct GLParamBuffer *next; 107 | } GLParamBuffer; 108 | 109 | typedef struct GLList { 110 | GLParamBuffer *first_op_buffer; 111 | /* TODO: extensions for an hash table or a better allocating scheme */ 112 | } GLList; 113 | 114 | typedef struct GLVertex { 115 | int edge_flag; 116 | V3 normal; 117 | V4 coord; 118 | V4 tex_coord; 119 | V4 color; 120 | 121 | /* computed values */ 122 | V4 ec; /* eye coordinates */ 123 | V4 pc; /* coordinates in the normalized volume */ 124 | int clip_code; /* clip code */ 125 | ZBufferPoint zp; /* integer coordinates for the rasterization */ 126 | } GLVertex; 127 | 128 | typedef struct GLImage { 129 | void *pixmap; 130 | int xsize,ysize; 131 | } GLImage; 132 | 133 | /* textures */ 134 | 135 | #define TEXTURE_HASH_TABLE_SIZE 256 136 | 137 | typedef struct GLTexture { 138 | GLImage images[MAX_TEXTURE_LEVELS]; 139 | int handle; 140 | struct GLTexture *next,*prev; 141 | } GLTexture; 142 | 143 | 144 | /* shared state */ 145 | 146 | typedef struct GLSharedState { 147 | GLList **lists; 148 | GLTexture **texture_hash_table; 149 | } GLSharedState; 150 | 151 | struct GLContext; 152 | 153 | typedef void (*gl_draw_triangle_func)(struct GLContext *c, 154 | GLVertex *p0,GLVertex *p1,GLVertex *p2); 155 | 156 | /* display context */ 157 | 158 | typedef struct GLContext { 159 | /* Z buffer */ 160 | ZBuffer *zb; 161 | 162 | /* lights */ 163 | GLLight lights[MAX_LIGHTS]; 164 | GLLight *first_light; 165 | V4 ambient_light_model; 166 | int local_light_model; 167 | int lighting_enabled; 168 | int light_model_two_side; 169 | 170 | /* materials */ 171 | GLMaterial materials[2]; 172 | int color_material_enabled; 173 | int current_color_material_mode; 174 | int current_color_material_type; 175 | 176 | /* textures */ 177 | GLTexture *current_texture; 178 | int texture_2d_enabled; 179 | 180 | /* shared state */ 181 | GLSharedState shared_state; 182 | 183 | /* current list */ 184 | GLParamBuffer *current_op_buffer; 185 | int current_op_buffer_index; 186 | int exec_flag,compile_flag,print_flag; 187 | 188 | /* matrix */ 189 | 190 | int matrix_mode; 191 | M4 *matrix_stack[3]; 192 | M4 *matrix_stack_ptr[3]; 193 | int matrix_stack_depth_max[3]; 194 | 195 | M4 matrix_model_view_inv; 196 | M4 matrix_model_projection; 197 | int matrix_model_projection_updated; 198 | int matrix_model_projection_no_w_transform; 199 | int apply_texture_matrix; 200 | 201 | /* viewport */ 202 | GLViewport viewport; 203 | 204 | /* current state */ 205 | int polygon_mode_back; 206 | int polygon_mode_front; 207 | 208 | int current_front_face; 209 | int current_shade_model; 210 | int current_cull_face; 211 | int cull_face_enabled; 212 | int normalize_enabled; 213 | gl_draw_triangle_func draw_triangle_front,draw_triangle_back; 214 | 215 | /* selection */ 216 | int render_mode; 217 | unsigned int *select_buffer; 218 | int select_size; 219 | unsigned int *select_ptr,*select_hit; 220 | int select_overflow; 221 | int select_hits; 222 | 223 | /* names */ 224 | unsigned int name_stack[MAX_NAME_STACK_DEPTH]; 225 | int name_stack_size; 226 | 227 | /* clear */ 228 | float clear_depth; 229 | V4 clear_color; 230 | 231 | /* current vertex state */ 232 | V4 current_color; 233 | unsigned int longcurrent_color[3]; /* precomputed integer color */ 234 | V4 current_normal; 235 | V4 current_tex_coord; 236 | int current_edge_flag; 237 | 238 | /* glBegin / glEnd */ 239 | int in_begin; 240 | int begin_type; 241 | int vertex_n,vertex_cnt; 242 | int vertex_max; 243 | GLVertex *vertex; 244 | 245 | /* opengl 1.1 arrays */ 246 | float *vertex_array; 247 | int vertex_array_size; 248 | int vertex_array_stride; 249 | float *normal_array; 250 | int normal_array_stride; 251 | float *color_array; 252 | int color_array_size; 253 | int color_array_stride; 254 | float *texcoord_array; 255 | int texcoord_array_size; 256 | int texcoord_array_stride; 257 | int client_states; 258 | 259 | /* opengl 1.1 polygon offset */ 260 | float offset_factor; 261 | float offset_units; 262 | int offset_states; 263 | 264 | /* specular buffer. could probably be shared between contexts, 265 | but that wouldn't be 100% thread safe */ 266 | GLSpecBuf *specbuf_first; 267 | int specbuf_used_counter; 268 | int specbuf_num_buffers; 269 | 270 | /* opaque structure for user's use */ 271 | void *opaque; 272 | /* resize viewport function */ 273 | int (*gl_resize_viewport)(struct GLContext *c,int *xsize,int *ysize); 274 | 275 | /* depth test */ 276 | int depth_test; 277 | } GLContext; 278 | 279 | extern GLContext *gl_ctx; 280 | 281 | void gl_add_op(GLParam *p); 282 | 283 | /* clip.c */ 284 | void gl_transform_to_viewport(GLContext *c,GLVertex *v); 285 | void gl_draw_triangle(GLContext *c,GLVertex *p0,GLVertex *p1,GLVertex *p2); 286 | void gl_draw_line(GLContext *c,GLVertex *p0,GLVertex *p1); 287 | void gl_draw_point(GLContext *c,GLVertex *p0); 288 | 289 | void gl_draw_triangle_point(GLContext *c, 290 | GLVertex *p0,GLVertex *p1,GLVertex *p2); 291 | void gl_draw_triangle_line(GLContext *c, 292 | GLVertex *p0,GLVertex *p1,GLVertex *p2); 293 | void gl_draw_triangle_fill(GLContext *c, 294 | GLVertex *p0,GLVertex *p1,GLVertex *p2); 295 | void gl_draw_triangle_select(GLContext *c, 296 | GLVertex *p0,GLVertex *p1,GLVertex *p2); 297 | 298 | /* matrix.c */ 299 | void gl_print_matrix(const float *m); 300 | /* 301 | void glopLoadIdentity(GLContext *c,GLParam *p); 302 | void glopTranslate(GLContext *c,GLParam *p);*/ 303 | 304 | /* light.c */ 305 | void gl_add_select(GLContext *c,unsigned int zmin,unsigned int zmax); 306 | void gl_enable_disable_light(GLContext *c,int light,int v); 307 | void gl_shade_vertex(GLContext *c,GLVertex *v); 308 | 309 | void glInitTextures(GLContext *c); 310 | void glEndTextures(GLContext *c); 311 | GLTexture *alloc_texture(GLContext *c,int h); 312 | 313 | /* image_util.c */ 314 | void gl_convertRGB_to_5R6G5B(unsigned short *pixmap,unsigned char *rgb, 315 | int xsize,int ysize); 316 | void gl_convertRGB_to_8A8R8G8B(unsigned int *pixmap, unsigned char *rgb, 317 | int xsize, int ysize); 318 | void gl_resizeImage(unsigned char *dest,int xsize_dest,int ysize_dest, 319 | unsigned char *src,int xsize_src,int ysize_src); 320 | void gl_resizeImageNoInterpolate(unsigned char *dest,int xsize_dest,int ysize_dest, 321 | unsigned char *src,int xsize_src,int ysize_src); 322 | 323 | GLContext *gl_get_context(void); 324 | 325 | void gl_fatal_error(char *format, ...); 326 | 327 | 328 | /* specular buffer "api" */ 329 | GLSpecBuf *specbuf_get_buffer(GLContext *c, const int shininess_i, 330 | const float shininess); 331 | 332 | #ifdef __BEOS__ 333 | void dprintf(const char *, ...); 334 | 335 | #else /* !BEOS */ 336 | 337 | #ifdef DEBUG 338 | 339 | #define dprintf(format, args...) \ 340 | fprintf(stderr,"In '%s': " format "\n",__FUNCTION__, ##args); 341 | 342 | #else 343 | 344 | #define dprintf(format, args...) 345 | 346 | #endif 347 | #endif /* !BEOS */ 348 | 349 | /* glopXXX functions */ 350 | 351 | #define ADD_OP(a,b,c) void glop ## a (GLContext *,GLParam *); 352 | #include "opinfo.h" 353 | 354 | /* this clip epsilon is needed to avoid some rounding errors after 355 | several clipping stages */ 356 | 357 | #define CLIP_EPSILON (1E-5) 358 | 359 | static inline int gl_clipcode(float x,float y,float z,float w1) 360 | { 361 | float w; 362 | 363 | w=w1 * (1.0 + CLIP_EPSILON); 364 | return (x<-w) | 365 | ((x>w)<<1) | 366 | ((y<-w)<<2) | 367 | ((y>w)<<3) | 368 | ((z<-w)<<4) | 369 | ((z>w)<<5) ; 370 | } 371 | 372 | #endif /* _tgl_zgl_h_ */ 373 | -------------------------------------------------------------------------------- /src/zline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "zbuffer.h" 3 | 4 | #define ZCMP(z,zpix) ((z) >= (zpix)) 5 | 6 | void ZB_plot(ZBuffer * zb, ZBufferPoint * p) 7 | { 8 | unsigned short *pz; 9 | PIXEL *pp; 10 | int zz; 11 | 12 | pz = zb->zbuf + (p->y * zb->xsize + p->x); 13 | pp = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p->y + p->x * PSZB); 14 | zz = p->z >> ZB_POINT_Z_FRAC_BITS; 15 | if (ZCMP(zz, *pz)) { 16 | #if TGL_FEATURE_RENDER_BITS == 24 17 | pp[0]=p->r>>8; 18 | pp[1]=p->g>>8; 19 | pp[2]=p->b>>8; 20 | #else 21 | *pp = RGB_TO_PIXEL(p->r, p->g, p->b); 22 | #endif 23 | *pz = zz; 24 | } 25 | } 26 | 27 | #define INTERP_Z 28 | static void ZB_line_flat_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2, 29 | int color) 30 | { 31 | #include "zline.h" 32 | } 33 | 34 | /* line with color interpolation */ 35 | #define INTERP_Z 36 | #define INTERP_RGB 37 | static void ZB_line_interp_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) 38 | { 39 | #include "zline.h" 40 | } 41 | 42 | /* no Z interpolation */ 43 | 44 | static void ZB_line_flat(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2, 45 | int color) 46 | { 47 | #include "zline.h" 48 | } 49 | 50 | #define INTERP_RGB 51 | static void ZB_line_interp(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) 52 | { 53 | #include "zline.h" 54 | } 55 | 56 | void ZB_line_z(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) 57 | { 58 | int color1, color2; 59 | 60 | color1 = RGB_TO_PIXEL(p1->r, p1->g, p1->b); 61 | color2 = RGB_TO_PIXEL(p2->r, p2->g, p2->b); 62 | 63 | /* choose if the line should have its color interpolated or not */ 64 | if (color1 == color2) { 65 | ZB_line_flat_z(zb, p1, p2, color1); 66 | } else { 67 | ZB_line_interp_z(zb, p1, p2); 68 | } 69 | } 70 | 71 | void ZB_line(ZBuffer * zb, ZBufferPoint * p1, ZBufferPoint * p2) 72 | { 73 | int color1, color2; 74 | 75 | color1 = RGB_TO_PIXEL(p1->r, p1->g, p1->b); 76 | color2 = RGB_TO_PIXEL(p2->r, p2->g, p2->b); 77 | 78 | /* choose if the line should have its color interpolated or not */ 79 | if (color1 == color2) { 80 | ZB_line_flat(zb, p1, p2, color1); 81 | } else { 82 | ZB_line_interp(zb, p1, p2); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/zline.h: -------------------------------------------------------------------------------- 1 | { 2 | int n, dx, dy, sx, pp_inc_1, pp_inc_2; 3 | register int a; 4 | register PIXEL *pp; 5 | #if defined(INTERP_RGB) || TGL_FEATURE_RENDER_BITS == 24 6 | register unsigned int r, g, b; 7 | #endif 8 | #ifdef INTERP_RGB 9 | register unsigned int rinc, ginc, binc; 10 | #endif 11 | #ifdef INTERP_Z 12 | register unsigned short *pz; 13 | int zinc; 14 | register int z, zz; 15 | #endif 16 | 17 | if (p1->y > p2->y || (p1->y == p2->y && p1->x > p2->x)) { 18 | ZBufferPoint *tmp; 19 | tmp = p1; 20 | p1 = p2; 21 | p2 = tmp; 22 | } 23 | sx = zb->xsize; 24 | pp = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p1->y + p1->x * PSZB); 25 | #ifdef INTERP_Z 26 | pz = zb->zbuf + (p1->y * sx + p1->x); 27 | z = p1->z; 28 | #endif 29 | 30 | dx = p2->x - p1->x; 31 | dy = p2->y - p1->y; 32 | #ifdef INTERP_RGB 33 | r = p2->r << 8; 34 | g = p2->g << 8; 35 | b = p2->b << 8; 36 | #elif TGL_FEATURE_RENDER_BITS == 24 37 | /* for 24 bits, we store the colors in different variables */ 38 | r = p2->r >> 8; 39 | g = p2->g >> 8; 40 | b = p2->b >> 8; 41 | #endif 42 | 43 | #ifdef INTERP_RGB 44 | #define RGB(x) x 45 | #if TGL_FEATURE_RENDER_BITS == 24 46 | #define RGBPIXEL pp[0] = r >> 16, pp[1] = g >> 16, pp[2] = b >> 16 47 | #else 48 | #define RGBPIXEL *pp = RGB_TO_PIXEL(r >> 8,g >> 8,b >> 8) 49 | #endif 50 | #else /* INTERP_RGB */ 51 | #define RGB(x) 52 | #if TGL_FEATURE_RENDER_BITS == 24 53 | #define RGBPIXEL pp[0] = r, pp[1] = g, pp[2] = b 54 | #else 55 | #define RGBPIXEL *pp = color 56 | #endif 57 | #endif /* INTERP_RGB */ 58 | 59 | #ifdef INTERP_Z 60 | #define ZZ(x) x 61 | #define PUTPIXEL() \ 62 | { \ 63 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 64 | if (ZCMP(zz,*pz)) { \ 65 | RGBPIXEL; \ 66 | *pz=zz; \ 67 | } \ 68 | } 69 | #else /* INTERP_Z */ 70 | #define ZZ(x) 71 | #define PUTPIXEL() RGBPIXEL 72 | #endif /* INTERP_Z */ 73 | 74 | #define DRAWLINE(dx,dy,inc_1,inc_2) \ 75 | n=dx;\ 76 | ZZ(zinc=(p2->z-p1->z)/n);\ 77 | RGB(rinc=((p2->r-p1->r) << 8)/n;\ 78 | ginc=((p2->g-p1->g) << 8)/n;\ 79 | binc=((p2->b-p1->b) << 8)/n);\ 80 | a=2*dy-dx;\ 81 | dy=2*dy;\ 82 | dx=2*dx-dy;\ 83 | pp_inc_1 = (inc_1) * PSZB;\ 84 | pp_inc_2 = (inc_2) * PSZB;\ 85 | do {\ 86 | PUTPIXEL();\ 87 | ZZ(z+=zinc);\ 88 | RGB(r+=rinc;g+=ginc;b+=binc);\ 89 | if (a>0) { pp=(PIXEL *)((char *)pp + pp_inc_1); ZZ(pz+=(inc_1)); a-=dx; }\ 90 | else { pp=(PIXEL *)((char *)pp + pp_inc_2); ZZ(pz+=(inc_2)); a+=dy; }\ 91 | } while (--n >= 0); 92 | 93 | /* fin macro */ 94 | 95 | if (dx == 0 && dy == 0) { 96 | PUTPIXEL(); 97 | } else if (dx > 0) { 98 | if (dx >= dy) { 99 | DRAWLINE(dx, dy, sx + 1, 1); 100 | } else { 101 | DRAWLINE(dy, dx, sx + 1, sx); 102 | } 103 | } else { 104 | dx = -dx; 105 | if (dx >= dy) { 106 | DRAWLINE(dx, dy, sx - 1, -1); 107 | } else { 108 | DRAWLINE(dy, dx, sx - 1, sx); 109 | } 110 | } 111 | } 112 | 113 | #undef INTERP_Z 114 | #undef INTERP_RGB 115 | 116 | /* internal defines */ 117 | #undef DRAWLINE 118 | #undef PUTPIXEL 119 | #undef ZZ 120 | #undef RGB 121 | #undef RGBPIXEL 122 | -------------------------------------------------------------------------------- /src/zmath.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kimperator/TinySDGL/8be349298d5ad8f920ae2349549e21b06b2cf0f3/src/zmath.c -------------------------------------------------------------------------------- /src/zmath.h: -------------------------------------------------------------------------------- 1 | #ifndef __ZMATH__ 2 | #define __ZMATH__ 3 | 4 | /* Matrix & Vertex */ 5 | 6 | typedef struct { 7 | float m[4][4]; 8 | } M4; 9 | 10 | typedef struct { 11 | float m[3][3]; 12 | } M3; 13 | 14 | typedef struct { 15 | float m[3][4]; 16 | } M34; 17 | 18 | 19 | #define X v[0] 20 | #define Y v[1] 21 | #define Z v[2] 22 | #define W v[3] 23 | 24 | typedef struct { 25 | float v[3]; 26 | } V3; 27 | 28 | typedef struct { 29 | float v[4]; 30 | } V4; 31 | 32 | void gl_M4_Id(M4 *a); 33 | int gl_M4_IsId(M4 *a); 34 | void gl_M4_Move(M4 *a,M4 *b); 35 | void gl_MoveV3(V3 *a,V3 *b); 36 | void gl_MulM4V3(V3 *a,M4 *b,V3 *c); 37 | void gl_MulM3V3(V3 *a,M4 *b,V3 *c); 38 | 39 | void gl_M4_MulV4(V4 * a,M4 *b,V4 * c); 40 | void gl_M4_InvOrtho(M4 *a,M4 b); 41 | void gl_M4_Inv(M4 *a,M4 *b); 42 | void gl_M4_Mul(M4 *c,M4 *a,M4 *b); 43 | void gl_M4_MulLeft(M4 *c,M4 *a); 44 | void gl_M4_Transpose(M4 *a,M4 *b); 45 | void gl_M4_Rotate(M4 *c,float t,int u); 46 | int gl_V3_Norm(V3 *a); 47 | 48 | V3 gl_V3_New(float x,float y,float z); 49 | V4 gl_V4_New(float x,float y,float z,float w); 50 | 51 | int gl_Matrix_Inv(float *r,float *m,int n); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/ztriangle.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "zbuffer.h" 3 | 4 | #define ZCMP(z,zpix) ((z) >= (zpix)) 5 | 6 | void ZB_fillTriangleFlat(ZBuffer *zb, 7 | ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) 8 | { 9 | #if TGL_FEATURE_RENDER_BITS == 24 10 | unsigned char colorR, colorG, colorB; 11 | #else 12 | int color; 13 | #endif 14 | 15 | #define INTERP_Z 16 | 17 | #if TGL_FEATURE_RENDER_BITS == 24 18 | 19 | #define DRAW_INIT() \ 20 | { \ 21 | colorR=p2->r>>8; \ 22 | colorG=p2->g>>8; \ 23 | colorB=p2->b>>8; \ 24 | } 25 | 26 | #define PUT_PIXEL(_a) \ 27 | { \ 28 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 29 | if (ZCMP(zz,pz[_a])) { \ 30 | pp[3 * _a]=colorR;\ 31 | pp[3 * _a + 1]=colorG;\ 32 | pp[3 * _a + 2]=colorB;\ 33 | pz[_a]=zz; \ 34 | }\ 35 | z+=dzdx; \ 36 | } 37 | 38 | #else 39 | 40 | #define DRAW_INIT() \ 41 | { \ 42 | color=RGB_TO_PIXEL(p2->r,p2->g,p2->b); \ 43 | } 44 | 45 | #define PUT_PIXEL(_a) \ 46 | { \ 47 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 48 | if (ZCMP(zz,pz[_a])) { \ 49 | pp[_a]=color; \ 50 | pz[_a]=zz; \ 51 | } \ 52 | z+=dzdx; \ 53 | } 54 | #endif /* TGL_FEATURE_RENDER_BITS == 24 */ 55 | 56 | #include "ztriangle.h" 57 | } 58 | 59 | /* 60 | * Smooth filled triangle. 61 | * The code below is very tricky :) 62 | */ 63 | 64 | void ZB_fillTriangleSmooth(ZBuffer *zb, 65 | ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) 66 | { 67 | #if TGL_FEATURE_RENDER_BITS == 16 68 | int _drgbdx; 69 | #endif 70 | 71 | #define INTERP_Z 72 | #define INTERP_RGB 73 | 74 | #define SAR_RND_TO_ZERO(v,n) (v / (1<> ZB_POINT_Z_FRAC_BITS; \ 85 | if (ZCMP(zz,pz[_a])) { \ 86 | pp[3 * _a]=or1 >> 8;\ 87 | pp[3 * _a + 1]=og1 >> 8;\ 88 | pp[3 * _a + 2]=ob1 >> 8;\ 89 | pz[_a]=zz; \ 90 | }\ 91 | z+=dzdx; \ 92 | og1+=dgdx; \ 93 | or1+=drdx; \ 94 | ob1+=dbdx; \ 95 | } 96 | 97 | #elif TGL_FEATURE_RENDER_BITS == 16 98 | 99 | #define DRAW_INIT() \ 100 | { \ 101 | _drgbdx=(SAR_RND_TO_ZERO(drdx,6) << 22) & 0xFFC00000; \ 102 | _drgbdx|=SAR_RND_TO_ZERO(dgdx,5) & 0x000007FF; \ 103 | _drgbdx|=(SAR_RND_TO_ZERO(dbdx,7) << 12) & 0x001FF000; \ 104 | } 105 | 106 | 107 | #define PUT_PIXEL(_a) \ 108 | { \ 109 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 110 | if (ZCMP(zz,pz[_a])) { \ 111 | tmp=rgb & 0xF81F07E0; \ 112 | pp[_a]=tmp | (tmp >> 16); \ 113 | pz[_a]=zz; \ 114 | } \ 115 | z+=dzdx; \ 116 | rgb=(rgb+drgbdx) & ( ~ 0x00200800); \ 117 | } 118 | 119 | #define DRAW_LINE() \ 120 | { \ 121 | register unsigned short *pz; \ 122 | register PIXEL *pp; \ 123 | register unsigned int tmp,z,zz,rgb,drgbdx; \ 124 | register int n; \ 125 | n=(x2 >> 16) - x1; \ 126 | pp=pp1+x1; \ 127 | pz=pz1+x1; \ 128 | z=z1; \ 129 | rgb=(r1 << 16) & 0xFFC00000; \ 130 | rgb|=(g1 >> 5) & 0x000007FF; \ 131 | rgb|=(b1 << 5) & 0x001FF000; \ 132 | drgbdx=_drgbdx; \ 133 | while (n>=3) { \ 134 | PUT_PIXEL(0); \ 135 | PUT_PIXEL(1); \ 136 | PUT_PIXEL(2); \ 137 | PUT_PIXEL(3); \ 138 | pz+=4; \ 139 | pp+=4; \ 140 | n-=4; \ 141 | } \ 142 | while (n>=0) { \ 143 | PUT_PIXEL(0); \ 144 | pz+=1; \ 145 | pp+=1; \ 146 | n-=1; \ 147 | } \ 148 | } 149 | 150 | #else 151 | 152 | #define DRAW_INIT() \ 153 | { \ 154 | } 155 | 156 | #define PUT_PIXEL(_a) \ 157 | { \ 158 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 159 | if (ZCMP(zz,pz[_a])) { \ 160 | pp[_a] = RGB_TO_PIXEL(or1, og1, ob1);\ 161 | pz[_a]=zz; \ 162 | }\ 163 | z+=dzdx; \ 164 | og1+=dgdx; \ 165 | or1+=drdx; \ 166 | ob1+=dbdx; \ 167 | } 168 | 169 | #endif /* TGL_FEATURE_RENDER_BITS */ 170 | 171 | #include "ztriangle.h" 172 | } 173 | 174 | void ZB_setTexture(ZBuffer *zb,PIXEL *texture) 175 | { 176 | zb->current_texture=texture; 177 | } 178 | 179 | void ZB_fillTriangleMapping(ZBuffer *zb, 180 | ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) 181 | { 182 | PIXEL *texture; 183 | 184 | #define INTERP_Z 185 | #define INTERP_ST 186 | 187 | #define DRAW_INIT() \ 188 | { \ 189 | texture=zb->current_texture; \ 190 | } 191 | 192 | #if TGL_FEATURE_RENDER_BITS == 24 193 | 194 | #define PUT_PIXEL(_a) \ 195 | { \ 196 | unsigned char *ptr;\ 197 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 198 | if (ZCMP(zz,pz[_a])) { \ 199 | ptr = texture + (((t & 0x3FC00000) | s) >> 14) * 3; \ 200 | pp[3 * _a]= ptr[0];\ 201 | pp[3 * _a + 1]= ptr[1];\ 202 | pp[3 * _a + 2]= ptr[2];\ 203 | pz[_a]=zz; \ 204 | } \ 205 | z+=dzdx; \ 206 | s+=dsdx; \ 207 | t+=dtdx; \ 208 | } 209 | 210 | #else 211 | 212 | #define PUT_PIXEL(_a) \ 213 | { \ 214 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 215 | if (ZCMP(zz,pz[_a])) { \ 216 | pp[_a]=texture[((t & 0x3FC00000) | s) >> 14]; \ 217 | pz[_a]=zz; \ 218 | } \ 219 | z+=dzdx; \ 220 | s+=dsdx; \ 221 | t+=dtdx; \ 222 | } 223 | 224 | #endif 225 | 226 | #include "ztriangle.h" 227 | } 228 | 229 | /* 230 | * Texture mapping with perspective correction. 231 | * We use the gradient method to make less divisions. 232 | * TODO: pipeline the division 233 | */ 234 | #if 1 235 | 236 | void ZB_fillTriangleMappingPerspective(ZBuffer *zb, 237 | ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) 238 | { 239 | PIXEL *texture; 240 | float fdzdx,fndzdx,ndszdx,ndtzdx; 241 | 242 | #define INTERP_Z 243 | #define INTERP_STZ 244 | 245 | #define NB_INTERP 8 246 | 247 | #define DRAW_INIT() \ 248 | { \ 249 | texture=zb->current_texture;\ 250 | fdzdx=(float)dzdx;\ 251 | fndzdx=NB_INTERP * fdzdx;\ 252 | ndszdx=NB_INTERP * dszdx;\ 253 | ndtzdx=NB_INTERP * dtzdx;\ 254 | } 255 | 256 | 257 | #if TGL_FEATURE_RENDER_BITS == 24 258 | 259 | #define PUT_PIXEL(_a) \ 260 | { \ 261 | unsigned char *ptr;\ 262 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 263 | if (ZCMP(zz,pz[_a])) { \ 264 | ptr = texture + (((t & 0x3FC00000) | (s & 0x003FC000)) >> 14) * 3;\ 265 | pp[3 * _a]= ptr[0];\ 266 | pp[3 * _a + 1]= ptr[1];\ 267 | pp[3 * _a + 2]= ptr[2];\ 268 | pz[_a]=zz; \ 269 | } \ 270 | z+=dzdx; \ 271 | s+=dsdx; \ 272 | t+=dtdx; \ 273 | } 274 | 275 | #else 276 | 277 | #define PUT_PIXEL(_a) \ 278 | { \ 279 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 280 | if (ZCMP(zz,pz[_a])) { \ 281 | pp[_a]=*(PIXEL *)((char *)texture+ \ 282 | (((t & 0x3FC00000) | (s & 0x003FC000)) >> (17 - PSZSH)));\ 283 | pz[_a]=zz; \ 284 | } \ 285 | z+=dzdx; \ 286 | s+=dsdx; \ 287 | t+=dtdx; \ 288 | } 289 | 290 | #endif 291 | 292 | #define DRAW_LINE() \ 293 | { \ 294 | register unsigned short *pz; \ 295 | register PIXEL *pp; \ 296 | register unsigned int s,t,z,zz; \ 297 | register int n,dsdx,dtdx; \ 298 | float sz,tz,fz,zinv; \ 299 | n=(x2>>16)-x1; \ 300 | fz=(float)z1;\ 301 | zinv=1.0 / fz;\ 302 | pp=(PIXEL *)((char *)pp1 + x1 * PSZB); \ 303 | pz=pz1+x1; \ 304 | z=z1; \ 305 | sz=sz1;\ 306 | tz=tz1;\ 307 | while (n>=(NB_INTERP-1)) { \ 308 | {\ 309 | float ss,tt;\ 310 | ss=(sz * zinv);\ 311 | tt=(tz * zinv);\ 312 | s=(int) ss;\ 313 | t=(int) tt;\ 314 | dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ 315 | dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ 316 | fz+=fndzdx;\ 317 | zinv=1.0 / fz;\ 318 | }\ 319 | PUT_PIXEL(0); \ 320 | PUT_PIXEL(1); \ 321 | PUT_PIXEL(2); \ 322 | PUT_PIXEL(3); \ 323 | PUT_PIXEL(4); \ 324 | PUT_PIXEL(5); \ 325 | PUT_PIXEL(6); \ 326 | PUT_PIXEL(7); \ 327 | pz+=NB_INTERP; \ 328 | pp=(PIXEL *)((char *)pp + NB_INTERP * PSZB);\ 329 | n-=NB_INTERP; \ 330 | sz+=ndszdx;\ 331 | tz+=ndtzdx;\ 332 | } \ 333 | {\ 334 | float ss,tt;\ 335 | ss=(sz * zinv);\ 336 | tt=(tz * zinv);\ 337 | s=(int) ss;\ 338 | t=(int) tt;\ 339 | dsdx= (int)( (dszdx - ss*fdzdx)*zinv );\ 340 | dtdx= (int)( (dtzdx - tt*fdzdx)*zinv );\ 341 | }\ 342 | while (n>=0) { \ 343 | PUT_PIXEL(0); \ 344 | pz+=1; \ 345 | pp=(PIXEL *)((char *)pp + PSZB);\ 346 | n-=1; \ 347 | } \ 348 | } 349 | 350 | #include "ztriangle.h" 351 | } 352 | 353 | #endif 354 | 355 | #if 0 356 | 357 | /* slow but exact version (only there for reference, incorrect for 24 358 | bits) */ 359 | 360 | void ZB_fillTriangleMappingPerspective(ZBuffer *zb, 361 | ZBufferPoint *p0,ZBufferPoint *p1,ZBufferPoint *p2) 362 | { 363 | PIXEL *texture; 364 | 365 | #define INTERP_Z 366 | #define INTERP_STZ 367 | 368 | #define DRAW_INIT() \ 369 | { \ 370 | texture=zb->current_texture; \ 371 | } 372 | 373 | #define PUT_PIXEL(_a) \ 374 | { \ 375 | float zinv; \ 376 | int s,t; \ 377 | zz=z >> ZB_POINT_Z_FRAC_BITS; \ 378 | if (ZCMP(zz,pz[_a])) { \ 379 | zinv= 1.0 / (float) z; \ 380 | s= (int) (sz * zinv); \ 381 | t= (int) (tz * zinv); \ 382 | pp[_a]=texture[((t & 0x3FC00000) | s) >> 14]; \ 383 | pz[_a]=zz; \ 384 | } \ 385 | z+=dzdx; \ 386 | sz+=dszdx; \ 387 | tz+=dtzdx; \ 388 | } 389 | 390 | #include "ztriangle.h" 391 | } 392 | 393 | 394 | #endif 395 | -------------------------------------------------------------------------------- /src/ztriangle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * We draw a triangle with various interpolations 3 | */ 4 | 5 | { 6 | ZBufferPoint *t,*pr1,*pr2,*l1,*l2; 7 | float fdx1, fdx2, fdy1, fdy2, fz, d1, d2; 8 | unsigned short *pz1; 9 | PIXEL *pp1; 10 | int part,update_left,update_right; 11 | 12 | int nb_lines,dx1,dy1,tmp,dx2,dy2; 13 | 14 | int error,derror; 15 | int x1,dxdy_min,dxdy_max; 16 | /* warning: x2 is multiplied by 2^16 */ 17 | int x2,dx2dy2; 18 | 19 | #ifdef INTERP_Z 20 | int z1,dzdx,dzdy,dzdl_min,dzdl_max; 21 | #endif 22 | #ifdef INTERP_RGB 23 | int r1,drdx,drdy,drdl_min,drdl_max; 24 | int g1,dgdx,dgdy,dgdl_min,dgdl_max; 25 | int b1,dbdx,dbdy,dbdl_min,dbdl_max; 26 | #endif 27 | #ifdef INTERP_ST 28 | int s1,dsdx,dsdy,dsdl_min,dsdl_max; 29 | int t1,dtdx,dtdy,dtdl_min,dtdl_max; 30 | #endif 31 | #ifdef INTERP_STZ 32 | float sz1,dszdx,dszdy,dszdl_min,dszdl_max; 33 | float tz1,dtzdx,dtzdy,dtzdl_min,dtzdl_max; 34 | #endif 35 | 36 | /* we sort the vertex with increasing y */ 37 | if (p1->y < p0->y) { 38 | t = p0; 39 | p0 = p1; 40 | p1 = t; 41 | } 42 | if (p2->y < p0->y) { 43 | t = p2; 44 | p2 = p1; 45 | p1 = p0; 46 | p0 = t; 47 | } else if (p2->y < p1->y) { 48 | t = p1; 49 | p1 = p2; 50 | p2 = t; 51 | } 52 | 53 | /* we compute dXdx and dXdy for all interpolated values */ 54 | 55 | fdx1 = p1->x - p0->x; 56 | fdy1 = p1->y - p0->y; 57 | 58 | fdx2 = p2->x - p0->x; 59 | fdy2 = p2->y - p0->y; 60 | 61 | fz = fdx1 * fdy2 - fdx2 * fdy1; 62 | if (fz == 0) 63 | return; 64 | fz = 1.0 / fz; 65 | 66 | fdx1 *= fz; 67 | fdy1 *= fz; 68 | fdx2 *= fz; 69 | fdy2 *= fz; 70 | 71 | #ifdef INTERP_Z 72 | d1 = p1->z - p0->z; 73 | d2 = p2->z - p0->z; 74 | dzdx = (int) (fdy2 * d1 - fdy1 * d2); 75 | dzdy = (int) (fdx1 * d2 - fdx2 * d1); 76 | #endif 77 | 78 | #ifdef INTERP_RGB 79 | d1 = p1->r - p0->r; 80 | d2 = p2->r - p0->r; 81 | drdx = (int) (fdy2 * d1 - fdy1 * d2); 82 | drdy = (int) (fdx1 * d2 - fdx2 * d1); 83 | 84 | d1 = p1->g - p0->g; 85 | d2 = p2->g - p0->g; 86 | dgdx = (int) (fdy2 * d1 - fdy1 * d2); 87 | dgdy = (int) (fdx1 * d2 - fdx2 * d1); 88 | 89 | d1 = p1->b - p0->b; 90 | d2 = p2->b - p0->b; 91 | dbdx = (int) (fdy2 * d1 - fdy1 * d2); 92 | dbdy = (int) (fdx1 * d2 - fdx2 * d1); 93 | 94 | #endif 95 | 96 | #ifdef INTERP_ST 97 | d1 = p1->s - p0->s; 98 | d2 = p2->s - p0->s; 99 | dsdx = (int) (fdy2 * d1 - fdy1 * d2); 100 | dsdy = (int) (fdx1 * d2 - fdx2 * d1); 101 | 102 | d1 = p1->t - p0->t; 103 | d2 = p2->t - p0->t; 104 | dtdx = (int) (fdy2 * d1 - fdy1 * d2); 105 | dtdy = (int) (fdx1 * d2 - fdx2 * d1); 106 | #endif 107 | 108 | #ifdef INTERP_STZ 109 | { 110 | float zz; 111 | zz=(float) p0->z; 112 | p0->sz= (float) p0->s * zz; 113 | p0->tz= (float) p0->t * zz; 114 | zz=(float) p1->z; 115 | p1->sz= (float) p1->s * zz; 116 | p1->tz= (float) p1->t * zz; 117 | zz=(float) p2->z; 118 | p2->sz= (float) p2->s * zz; 119 | p2->tz= (float) p2->t * zz; 120 | 121 | d1 = p1->sz - p0->sz; 122 | d2 = p2->sz - p0->sz; 123 | dszdx = (fdy2 * d1 - fdy1 * d2); 124 | dszdy = (fdx1 * d2 - fdx2 * d1); 125 | 126 | d1 = p1->tz - p0->tz; 127 | d2 = p2->tz - p0->tz; 128 | dtzdx = (fdy2 * d1 - fdy1 * d2); 129 | dtzdy = (fdx1 * d2 - fdx2 * d1); 130 | } 131 | #endif 132 | 133 | /* screen coordinates */ 134 | 135 | pp1 = (PIXEL *) ((char *) zb->pbuf + zb->linesize * p0->y); 136 | pz1 = zb->zbuf + p0->y * zb->xsize; 137 | 138 | DRAW_INIT(); 139 | 140 | for(part=0;part<2;part++) { 141 | if (part == 0) { 142 | if (fz > 0) { 143 | update_left=1; 144 | update_right=1; 145 | l1=p0; 146 | l2=p2; 147 | pr1=p0; 148 | pr2=p1; 149 | } else { 150 | update_left=1; 151 | update_right=1; 152 | l1=p0; 153 | l2=p1; 154 | pr1=p0; 155 | pr2=p2; 156 | } 157 | nb_lines = p1->y - p0->y; 158 | } else { 159 | /* second part */ 160 | if (fz > 0) { 161 | update_left=0; 162 | update_right=1; 163 | pr1=p1; 164 | pr2=p2; 165 | } else { 166 | update_left=1; 167 | update_right=0; 168 | l1=p1; 169 | l2=p2; 170 | } 171 | nb_lines = p2->y - p1->y + 1; 172 | } 173 | 174 | /* compute the values for the left edge */ 175 | 176 | if (update_left) { 177 | dy1 = l2->y - l1->y; 178 | dx1 = l2->x - l1->x; 179 | if (dy1 > 0) 180 | tmp = (dx1 << 16) / dy1; 181 | else 182 | tmp = 0; 183 | x1 = l1->x; 184 | error = 0; 185 | derror = tmp & 0x0000ffff; 186 | dxdy_min = tmp >> 16; 187 | dxdy_max = dxdy_min + 1; 188 | 189 | #ifdef INTERP_Z 190 | z1=l1->z; 191 | dzdl_min=(dzdy + dzdx * dxdy_min); 192 | dzdl_max=dzdl_min + dzdx; 193 | #endif 194 | #ifdef INTERP_RGB 195 | r1=l1->r; 196 | drdl_min=(drdy + drdx * dxdy_min); 197 | drdl_max=drdl_min + drdx; 198 | 199 | g1=l1->g; 200 | dgdl_min=(dgdy + dgdx * dxdy_min); 201 | dgdl_max=dgdl_min + dgdx; 202 | 203 | b1=l1->b; 204 | dbdl_min=(dbdy + dbdx * dxdy_min); 205 | dbdl_max=dbdl_min + dbdx; 206 | #endif 207 | #ifdef INTERP_ST 208 | s1=l1->s; 209 | dsdl_min=(dsdy + dsdx * dxdy_min); 210 | dsdl_max=dsdl_min + dsdx; 211 | 212 | t1=l1->t; 213 | dtdl_min=(dtdy + dtdx * dxdy_min); 214 | dtdl_max=dtdl_min + dtdx; 215 | #endif 216 | #ifdef INTERP_STZ 217 | sz1=l1->sz; 218 | dszdl_min=(dszdy + dszdx * dxdy_min); 219 | dszdl_max=dszdl_min + dszdx; 220 | 221 | tz1=l1->tz; 222 | dtzdl_min=(dtzdy + dtzdx * dxdy_min); 223 | dtzdl_max=dtzdl_min + dtzdx; 224 | #endif 225 | } 226 | 227 | /* compute values for the right edge */ 228 | 229 | if (update_right) { 230 | dx2 = (pr2->x - pr1->x); 231 | dy2 = (pr2->y - pr1->y); 232 | if (dy2>0) 233 | dx2dy2 = ( dx2 << 16) / dy2; 234 | else 235 | dx2dy2 = 0; 236 | x2 = pr1->x << 16; 237 | } 238 | 239 | /* we draw all the scan line of the part */ 240 | 241 | while (nb_lines>0) { 242 | nb_lines--; 243 | #ifndef DRAW_LINE 244 | /* generic draw line */ 245 | { 246 | register PIXEL *pp; 247 | register int n; 248 | #ifdef INTERP_Z 249 | register unsigned short *pz; 250 | register unsigned int z,zz; 251 | #endif 252 | #ifdef INTERP_RGB 253 | register unsigned int or1,og1,ob1; 254 | #endif 255 | #ifdef INTERP_ST 256 | register unsigned int s,t; 257 | #endif 258 | #ifdef INTERP_STZ 259 | float sz,tz; 260 | #endif 261 | 262 | n=(x2 >> 16) - x1; 263 | pp=(PIXEL *)((char *)pp1 + x1 * PSZB); 264 | #ifdef INTERP_Z 265 | pz=pz1+x1; 266 | z=z1; 267 | #endif 268 | #ifdef INTERP_RGB 269 | or1 = r1; 270 | og1 = g1; 271 | ob1 = b1; 272 | #endif 273 | #ifdef INTERP_ST 274 | s=s1; 275 | t=t1; 276 | #endif 277 | #ifdef INTERP_STZ 278 | sz=sz1; 279 | tz=tz1; 280 | #endif 281 | while (n>=3) { 282 | PUT_PIXEL(0); 283 | PUT_PIXEL(1); 284 | PUT_PIXEL(2); 285 | PUT_PIXEL(3); 286 | #ifdef INTERP_Z 287 | pz+=4; 288 | #endif 289 | pp=(PIXEL *)((char *)pp + 4 * PSZB); 290 | n-=4; 291 | } 292 | while (n>=0) { 293 | PUT_PIXEL(0); 294 | #ifdef INTERP_Z 295 | pz+=1; 296 | #endif 297 | pp=(PIXEL *)((char *)pp + PSZB); 298 | n-=1; 299 | } 300 | } 301 | #else 302 | DRAW_LINE(); 303 | #endif 304 | 305 | /* left edge */ 306 | error+=derror; 307 | if (error > 0) { 308 | error-=0x10000; 309 | x1+=dxdy_max; 310 | #ifdef INTERP_Z 311 | z1+=dzdl_max; 312 | #endif 313 | #ifdef INTERP_RGB 314 | r1+=drdl_max; 315 | g1+=dgdl_max; 316 | b1+=dbdl_max; 317 | #endif 318 | #ifdef INTERP_ST 319 | s1+=dsdl_max; 320 | t1+=dtdl_max; 321 | #endif 322 | #ifdef INTERP_STZ 323 | sz1+=dszdl_max; 324 | tz1+=dtzdl_max; 325 | #endif 326 | } else { 327 | x1+=dxdy_min; 328 | #ifdef INTERP_Z 329 | z1+=dzdl_min; 330 | #endif 331 | #ifdef INTERP_RGB 332 | r1+=drdl_min; 333 | g1+=dgdl_min; 334 | b1+=dbdl_min; 335 | #endif 336 | #ifdef INTERP_ST 337 | s1+=dsdl_min; 338 | t1+=dtdl_min; 339 | #endif 340 | #ifdef INTERP_STZ 341 | sz1+=dszdl_min; 342 | tz1+=dtzdl_min; 343 | #endif 344 | } 345 | 346 | /* right edge */ 347 | x2+=dx2dy2; 348 | 349 | /* screen coordinates */ 350 | pp1=(PIXEL *)((char *)pp1 + zb->linesize); 351 | pz1+=zb->xsize; 352 | } 353 | } 354 | } 355 | 356 | #undef INTERP_Z 357 | #undef INTERP_RGB 358 | #undef INTERP_ST 359 | #undef INTERP_STZ 360 | 361 | #undef DRAW_INIT 362 | #undef DRAW_LINE 363 | #undef PUT_PIXEL 364 | --------------------------------------------------------------------------------