#include "vk_triapi.h" #include "vk_geometry.h" #include "vk_render.h" #include "vk_sprite.h" // R_GetSpriteTexture #include "vk_logs.h" #include "xash3d_mathlib.h" #define MAX_TRIAPI_VERTICES 1024 #define MAX_TRIAPI_INDICES 4096 static struct { vk_vertex_t vertices[MAX_TRIAPI_VERTICES]; uint16_t indices[MAX_TRIAPI_INDICES]; int num_vertices; int primitive_mode; int texture_index; vk_render_type_e render_type; qboolean initialized; } g_triapi = {0}; void TriSetTexture( int texture_index ) { g_triapi.texture_index = texture_index; } int TriSpriteTexture( model_t *pSpriteModel, int frame ) { int gl_texturenum; if(( gl_texturenum = R_GetSpriteTexture( pSpriteModel, frame )) <= 0 ) return 0; TriSetTexture( gl_texturenum ); return 1; } void TriRenderMode( int render_mode ) { switch( render_mode ) { case kRenderTransAlpha: g_triapi.render_type = kVkRenderType_A_1mA_R; break; case kRenderTransColor: case kRenderTransTexture: g_triapi.render_type = kVkRenderType_A_1mA_RW; break; case kRenderGlow: case kRenderTransAdd: g_triapi.render_type = kVkRenderType_A_1_R; break; case kRenderNormal: default: g_triapi.render_type = kVkRenderTypeSolid; break; } } void TriBegin( int primitive_mode ) { ASSERT(!g_triapi.primitive_mode); switch(primitive_mode) { case TRI_TRIANGLES: break; case TRI_TRIANGLE_STRIP: break; case TRI_QUADS: break; default: gEngine.Con_Printf(S_ERROR "TriBegin: unsupported primitive_mode %d\n", primitive_mode); return; } vk_vertex_t *const ve = g_triapi.vertices + 0; if (g_triapi.num_vertices > 1) *ve = g_triapi.vertices[g_triapi.num_vertices-1]; if (!g_triapi.initialized) { Vector4Set(ve->color, 255, 255, 255, 255); g_triapi.initialized = true; } g_triapi.primitive_mode = primitive_mode + 1; g_triapi.num_vertices = 0; } /* static int genTrianglesIndices(void) { */ /* return 0; */ /* } */ static int genQuadsIndices(void) { int num_indices = 0; uint16_t *const dst_idx = g_triapi.indices; for (int i = 0; i < g_triapi.num_vertices - 3; i+=4) { if (num_indices > MAX_TRIAPI_INDICES - 6) { gEngine.Con_Printf(S_ERROR "Triapi ran out of indices space, max %d (vertices=%d)\n", MAX_TRIAPI_INDICES, g_triapi.num_vertices); break; } dst_idx[num_indices++] = 0 + i; dst_idx[num_indices++] = 1 + i; dst_idx[num_indices++] = 2 + i; dst_idx[num_indices++] = 0 + i; dst_idx[num_indices++] = 2 + i; dst_idx[num_indices++] = 3 + i; } return num_indices; } static int genTriangleStripIndices(void) { int num_indices = 0; uint16_t *const dst_idx = g_triapi.indices; for (int i = 2; i < g_triapi.num_vertices; ++i) { if (num_indices > MAX_TRIAPI_INDICES - 3) { gEngine.Con_Printf(S_ERROR "Triapi ran out of indices space, max %d (vertices=%d)\n", MAX_TRIAPI_INDICES, g_triapi.num_vertices); break; } if( i & 1 ) { // draw triangle [n-1 n-2 n] dst_idx[num_indices++] = i - 1; dst_idx[num_indices++] = i - 2; dst_idx[num_indices++] = i; } else { // draw triangle [n-2 n-1 n] dst_idx[num_indices++] = i - 2; dst_idx[num_indices++] = i - 1; dst_idx[num_indices++] = i; } } return num_indices; } void TriEnd( void ) { if (!g_triapi.primitive_mode) return; const vk_vertex_t *const v = g_triapi.vertices + g_triapi.num_vertices - 1; const vec4_t color = {v->color[0] / 255.f, v->color[1] / 255.f, v->color[2] / 255.f, 1.f}; TriEndEx( color, "unnamed triapi" ); } void TriEndEx( const vec4_t color, const char* name ) { if (!g_triapi.primitive_mode) return; int num_indices = 0; switch(g_triapi.primitive_mode - 1) { /* case TRI_TRIANGLES: */ /* num_indices = genTrianglesIndices(); */ /* break; */ case TRI_TRIANGLE_STRIP: num_indices = genTriangleStripIndices(); break; case TRI_QUADS: num_indices = genQuadsIndices(); break; default: gEngine.Con_Printf(S_ERROR "TriEnd: unsupported primitive_mode %d\n", g_triapi.primitive_mode - 1); break; } if (num_indices) { R_RenderDrawOnce((r_draw_once_t){ .name = name, .vertices = g_triapi.vertices, .indices = g_triapi.indices, .vertices_count = g_triapi.num_vertices, .indices_count = num_indices, .render_type = g_triapi.render_type, .material = R_VkMaterialGetForTexture(g_triapi.texture_index), .ye_olde_texture = g_triapi.texture_index, .emissive = (const vec4_t*)color, .color = (const vec4_t*)color, }); } g_triapi.num_vertices = 0; g_triapi.primitive_mode = 0; } void TriTexCoord2f( float u, float v ) { vk_vertex_t *const ve = g_triapi.vertices + g_triapi.num_vertices; Vector2Set(ve->gl_tc, u, v); } void TriVertex3fv( const float *v ) { TriVertex3f(v[0], v[1], v[2]); } void TriVertex3f( float x, float y, float z ) { if (g_triapi.num_vertices == MAX_TRIAPI_VERTICES - 1) { ERROR_THROTTLED(1, "vk TriApi: trying to emit more than %d vertices in one batch\n", MAX_TRIAPI_VERTICES); return; } vk_vertex_t *const ve = g_triapi.vertices + g_triapi.num_vertices; VectorSet(ve->pos, x, y, z); // Emit vertex preserving previous vertex values ++g_triapi.num_vertices; g_triapi.vertices[g_triapi.num_vertices] = g_triapi.vertices[g_triapi.num_vertices-1]; } void TriColor4ub_( byte r, byte g, byte b, byte a ) { Vector4Set(g_triapi.vertices[g_triapi.num_vertices].color, r, g, b, a); } void TriColor4f( float r, float g, float b, float a ) { TriColor4ub_( clampi32(r*255.f, 0, 255), clampi32(g*255.f, 0, 255), clampi32(b*255.f, 0, 255), clampi32(a*255.f, 0, 255)); } void TriNormal3fv( const float *v ) { TriNormal3f(v[0], v[1], v[2]); } void TriNormal3f( float x, float y, float z ) { vk_vertex_t *const ve = g_triapi.vertices + g_triapi.num_vertices; VectorSet(ve->normal, x, y, z); }