/*************************************************************************** * * * Project64-video - A Nintendo 64 gfx plugin. * * http://www.pj64-emu.com/ * * Copyright (C) 2017 Project64. All rights reserved. * * Copyright (C) 2003-2009 Sergey 'Gonetz' Lipski * * Copyright (C) 2002 Dave2001 * * * * License: * * GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * * version 2 of the License, or (at your option) any later version. * * * ****************************************************************************/ #include #include #ifdef _WIN32 #include #endif // _WIN32 #include "glide.h" #include "glitchmain.h" #include #include #define Z_MAX (65536.0f) #define VERTEX_SIZE sizeof(VERTEX) //Size of vertex struct static int xy_off; static int xy_en; static int z_en; static int z_off; static int q_off; static int q_en; static int pargb_off; static int pargb_en; static int st0_off; static int st0_en; static int st1_off; static int st1_en; static int fog_ext_off; static int fog_ext_en; int w_buffer_mode; int inverted_culling; int culling_mode; #define VERTEX_BUFFER_SIZE 1500 //Max amount of vertices to buffer, this seems large enough. static VERTEX vertex_buffer[VERTEX_BUFFER_SIZE]; static int vertex_buffer_count = 0; static GLenum vertex_draw_mode; static bool vertex_buffer_enabled = false; void vbo_draw() { if (vertex_buffer_count) { WriteTrace(TraceGlide64, TraceDebug, "vertex_draw_mode: %d vertex_buffer_count: %d", vertex_draw_mode, vertex_buffer_count); glDrawArrays(vertex_draw_mode, 0, vertex_buffer_count); vertex_buffer_count = 0; WriteTrace(TraceGlide64, TraceDebug, "done (glGetError() = %X)", glGetError()); } } //Buffer vertices instead of glDrawArrays(...) void vbo_buffer(GLenum mode, GLint first, GLsizei count, void* pointers) { if ((count != 3 && mode != GL_TRIANGLES) || vertex_buffer_count + count > VERTEX_BUFFER_SIZE) { vbo_draw(); } memcpy(&vertex_buffer[vertex_buffer_count], pointers, count * VERTEX_SIZE); vertex_buffer_count += count; if (count == 3 || mode == GL_TRIANGLES) { vertex_draw_mode = GL_TRIANGLES; } else { vertex_draw_mode = mode; vbo_draw(); //Triangle fans and strips can't be joined as easily, just draw them straight away. } } void vbo_enable() { if (vertex_buffer_enabled) return; vertex_buffer_enabled = true; glEnableVertexAttribArray(POSITION_ATTR); glVertexAttribPointer(POSITION_ATTR, 4, GL_FLOAT, GL_FALSE, VERTEX_SIZE, &vertex_buffer[0].x); //Position glEnableVertexAttribArray(COLOUR_ATTR); glVertexAttribPointer(COLOUR_ATTR, 4, GL_UNSIGNED_BYTE, GL_TRUE, VERTEX_SIZE, &vertex_buffer[0].b); //Colour glEnableVertexAttribArray(TEXCOORD_0_ATTR); glVertexAttribPointer(TEXCOORD_0_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[2]); //Tex0 glEnableVertexAttribArray(TEXCOORD_1_ATTR); glVertexAttribPointer(TEXCOORD_1_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[0]); //Tex1 glEnableVertexAttribArray(FOG_ATTR); glVertexAttribPointer(FOG_ATTR, 1, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].f); //Fog } void vbo_disable() { vbo_draw(); vertex_buffer_enabled = false; } inline float ZCALC(const float & z, const float & q) { float res = z_en ? ((z) / Z_MAX) / (q) : 1.0f; return res; } /* #define zclamp (1.0f-1.0f/zscale) static inline void zclamp_glVertex4f(float a, float b, float c, float d) { if (c VERTEX_BUFFER_SIZE) { vbo_draw(); } vertex_draw_mode = GL_TRIANGLES; memcpy(&vertex_buffer[vertex_buffer_count], a, VERTEX_SIZE); memcpy(&vertex_buffer[vertex_buffer_count + 1], b, VERTEX_SIZE); memcpy(&vertex_buffer[vertex_buffer_count + 2], c, VERTEX_SIZE); vertex_buffer_count += 3; WriteTrace(TraceGlitch, TraceDebug, "Done"); } void gfxDrawLine(const void *a, const void *b) { } void gfxDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers2) { void **pointers = (void**)pointers2; WriteTrace(TraceGlitch, TraceDebug, "gfxDrawVertexArray(%d,%d)\r\n", mode, Count); if (nvidia_viewport_hack && !render_to_texture) { glViewport(0, g_viewport_offset, viewport_width, viewport_height); nvidia_viewport_hack = 0; } reloadTexture(); if (need_to_compile) compile_shader(); if (mode != GR_TRIANGLE_FAN) { WriteTrace(TraceGlitch, TraceWarning, "gfxDrawVertexArray : unknown mode : %x", mode); } vbo_enable(); vbo_buffer(GL_TRIANGLE_FAN, 0, Count, pointers[0]); } void gfxDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride) { WriteTrace(TraceGlitch, TraceDebug, "gfxDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride); if (nvidia_viewport_hack && !render_to_texture) { glViewport(0, g_viewport_offset, viewport_width, viewport_height); nvidia_viewport_hack = 0; } if (stride != 156) { //LOGINFO("Incompatible stride\n"); } reloadTexture(); if (need_to_compile) compile_shader(); vbo_enable(); switch (mode) { case GR_TRIANGLE_STRIP: vbo_buffer(GL_TRIANGLE_STRIP, 0, Count, pointers); break; case GR_TRIANGLE_FAN: vbo_buffer(GL_TRIANGLE_FAN, 0, Count, pointers); break; default: WriteTrace(TraceGlitch, TraceWarning, "gfxDrawVertexArrayContiguous : unknown mode : %x", mode); } }