/* \brief clear scene */ GLHCKAPI void glhckRenderClear(unsigned int bufferBits) { GLHCK_INITIALIZED(); CALL(2, "%u", bufferBits); if (!_glhckRenderInitialized()) return; GLHCKRA()->clear(bufferBits); }
/* \brief give current program time to glhck */ GLHCKAPI void glhckRenderTime(float time) { GLHCK_INITIALIZED(); CALL(2, "%f", time); if (!_glhckRenderInitialized()) return; GLHCKRA()->time(time); }
/* \brief set view matrix */ GLHCKAPI void glhckRenderView(const kmMat4 *mat) { GLHCK_INITIALIZED(); CALL(2, "%p", mat); if (!_glhckRenderInitialized()) return; GLHCKRA()->setView(mat); memcpy(&GLHCKRD()->view.view, mat, sizeof(kmMat4)); }
/* \brief set clear color to render */ GLHCKAPI void glhckRenderClearColor(const glhckColorb *color) { GLHCK_INITIALIZED(); CALL(2, "%p", color); if (!_glhckRenderInitialized()) return; GLHCKRA()->clearColor(color); memcpy(&GLHCKRP()->clearColor, color, sizeof(glhckColorb)); }
/* \brief close the virutal display */ GLHCKAPI void glhckDisplayClose(void) { GLHCK_INITIALIZED(); TRACE(0); if (!_glhckRenderInitialized()) return; memset(&GLHCKR()->features, 0, sizeof(glhckRenderFeatures)); GLHCKRA()->terminate(); GLHCKR()->type = GLHCK_RENDER_AUTO; }
/* \brief set renderer's viewport */ GLHCKAPI void glhckRenderViewport(const glhckRect *viewport) { kmMat4 ortho; GLHCK_INITIALIZED(); CALL(1, RECTS, RECT(viewport)); assert(viewport->x >= 0 && viewport->y >= 0 && viewport->w > 0 && viewport->h > 0); if (!_glhckRenderInitialized()) return; /* set viewport on render */ GLHCKRA()->viewport(viewport->x, viewport->y, viewport->w, viewport->h); memcpy(&GLHCKRP()->viewport, viewport, sizeof(glhckRect)); /* update orthographic matrix */ kmMat4OrthographicProjection(&ortho, viewport->x, viewport->w, viewport->h, viewport->y, -1.0f, 1.0f); GLHCKRA()->setOrthographic(&ortho); memcpy(&GLHCKRD()->view.orthographic, &ortho, sizeof(kmMat4)); }
/* \brief clear scene */ GLHCKAPI void glhckRenderClear(unsigned int bufferBits) { GLHCK_INITIALIZED(); CALL(2, "%u", bufferBits); if (!_glhckRenderInitialized()) return; #if EMSCRIPTEN /* when there is no framebuffers bound assume we are in * main loop don't do clear since webgl does clear itself. * XXX: document this behaviour */ int i; for (i = 0; i < GLHCK_FRAMEBUFFER_TYPE_LAST && !GLHCKRD()->framebuffer[i]; ++i); if (i == GLHCK_FRAMEBUFFER_TYPE_LAST) return; #endif GLHCKRA()->clear(bufferBits); }
/* \brief resize render viewport internally */ GLHCKAPI void glhckRenderResize(int width, int height) { GLHCK_INITIALIZED(); CALL(1, "%d, %d", width, height); assert(width > 0 && height > 0); if (!_glhckRenderInitialized()) return; /* nothing to resize */ if (GLHCKR()->width == width && GLHCKR()->height == height) return; /* update all cameras */ _glhckCameraWorldUpdate(width, height); /* update on library last, so functions know the old values */ GLHCKR()->width = width; GLHCKR()->height = height; }
/* \brief creates virtual display and inits renderer */ GLHCKAPI int glhckDisplayCreate(int width, int height, glhckRenderType renderType) { GLHCK_INITIALIZED(); CALL(0, "%d, %d, %d", width, height, renderType); if (width <= 0 && height <= 0) goto fail; /* close display if created already */ if (GLHCKR()->type == renderType && renderType != GLHCK_RENDER_AUTO) goto success; else glhckDisplayClose(); /* init renderer */ switch (renderType) { case GLHCK_RENDER_AUTO: #ifdef GLHCK_HAS_OPENGL _glhckRenderOpenGL(); if (_glhckRenderInitialized()) break; #endif #ifdef GLHCK_HAS_OPENGL_FIXED_PIPELINE _glhckRenderOpenGLFixedPipeline(); if (_glhckRenderInitialized()) break; #endif _glhckRenderStub(); break; case GLHCK_RENDER_OPENGL: case GLHCK_RENDER_GLES2: #ifdef GLHCK_HAS_OPENGL _glhckRenderOpenGL(); #else DEBUG(GLHCK_DBG_ERROR, "OpenGL support was not compiled in!"); #endif break; case GLHCK_RENDER_OPENGL_FIXED_PIPELINE: case GLHCK_RENDER_GLES1: #ifdef GLHCK_HAS_OPENGL_FIXED_PIPELINE _glhckRenderOpenGLFixedPipeline(); #else DEBUG(GLHCK_DBG_ERROR, "OpenGL Fixed Pipeline support was not compiled in!"); #endif break; case GLHCK_RENDER_STUB: default: _glhckRenderStub(); break; } /* check that initialization was success */ if (!_glhckRenderInitialized()) goto fail; /* check render api and output warnings, * if any function is missing */ _glhckRenderCheckApi(); GLHCKR()->type = renderType; /* default render pass bits */ glhckRenderPass(glhckRenderPassDefaults()); /* default cull face */ glhckRenderCullFace(GLHCK_BACK); /* counter-clockwise are front face by default */ glhckRenderFrontFace(GLHCK_CCW); /* resize display */ glhckDisplayResize(width, height); success: RET(0, "%d", RETURN_OK); return RETURN_OK; fail: RET(0, "%d", RETURN_FAIL); return RETURN_FAIL; }
/* \brief render scene */ GLHCKAPI void glhckRender(void) { unsigned int ti, oi, ts, os, tc, oc; char kt; glhckTexture *t; glhckObject *o; __GLHCKobjectQueue *objects; __GLHCKtextureQueue *textures; GLHCK_INITIALIZED(); TRACE(2); /* can't render */ if (!glhckInitialized() || !_glhckRenderInitialized()) return; objects = &GLHCKRD()->objects; textures = &GLHCKRD()->textures; /* store counts for enumeration, +1 for untexture objects */ tc = textures->count+1; oc = objects->count; /* nothing to draw */ if (!oc) return; /* draw in sorted texture order */ for (ti = 0, ts = 0; ti != tc; ++ti) { if (ti < tc-1) { if (!(t = textures->queue[ti])) continue; } else t = NULL; /* untextured object */ for (oi = 0, os = 0, kt = 0; oi != oc; ++oi) { if (!(o = objects->queue[oi])) continue; if (o->material) { /* don't draw if not same texture or opaque, * opaque objects are drawn last */ if (o->material->texture != t || (o->material->blenda != GLHCK_ZERO || o->material->blendb != GLHCK_ZERO)) { if (o->material->texture == t) kt = 1; /* don't remove texture from queue */ if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } } else if (t) { /* no material, but texture requested */ if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } /* render object */ glhckObjectRender(o); glhckObjectFree(o); /* referenced on draw call */ objects->queue[oi] = NULL; --objects->count; } /* check if we need texture again or not */ if (kt) { if (ts != ti) textures->queue[ti] = NULL; textures->queue[ts++] = t; } else { if (t) { glhckTextureFree(t); /* ref is increased on draw call! */ textures->queue[ti] = NULL; --textures->count; } } } /* store counts for enumeration, +1 for untextured objects */ tc = textures->count+1; oc = objects->count; /* FIXME: shift queue here */ if (oc) { } /* draw opaque objects next, * FIXME: this should not be done in texture order, * instead draw from farthest to nearest. (I hate opaque objects) */ for (ti = 0; ti != tc && oc; ++ti) { if (ti < tc-1) { if (!(t = textures->queue[ti])) continue; } else t = NULL; /* untextured object */ for (oi = 0, os = 0; oi != oc; ++oi) { if (!(o = objects->queue[oi])) continue; if (o->material) { /* don't draw if not same texture */ if (o->material->texture != t) { if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } } else if (t) { if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } /* render object */ glhckObjectRender(o); glhckObjectFree(o); /* referenced on draw call */ objects->queue[oi] = NULL; --objects->count; } /* this texture is done for */ if (t) { glhckTextureFree(t); /* ref is increased on draw call! */ textures->queue[ti] = NULL; --textures->count; } /* no texture, time to break */ if (!t) break; } /* FIXME: shift queue here if leftovers */ /* good we got no leftovers \o/ */ if (objects->count) { /* something was left un-drawn :o? */ for (oi = 0; oi != objects->count; ++oi) glhckObjectFree(objects->queue[oi]); memset(objects->queue, 0, objects->count * sizeof(glhckObject*)); objects->count = 0; } if (textures->count) { /* something was left un-drawn :o? */ DEBUG(GLHCK_DBG_CRAP, "COUNT UNLEFT %u", textures->count); for (ti = 0; ti != textures->count; ++ti) glhckTextureFree(textures->queue[ti]); memset(textures->queue, 0, textures->count * sizeof(glhckTexture*)); textures->count = 0; } }