xash3d-fwgs/ref/vk/vk_triapi.c

225 lines
5.6 KiB
C

#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);
}