void draw() { fbo1.draw(render_tri); fbo2.draw(render_quad); // render to screen prep_ortho(); //render(); switch(mode) { case 1: render_tri(); break; case 2: render_quad(); break; case 3: render_from_texture(); break; } glfwSwapBuffers(window); glfwPollEvents(); }
bool Abstract_shader::render(Gl_img_helper::Disp_mode dmode, Gl_img_helper::Flip_mode fmode, const GLuint* fbo_buffs, int size) { if (bind_program()) { render_quad(vetex_attrib_id(), dmode, fmode, fbo_buffs, size); program.release(); return true; } return false; }
void render_player(Lightcycle *player) { Tail *tail = player->tail; float x = player->location.x - (field_w/2.0f); float y = player->location.y - (field_h/2.0f); render_quad(x, y); if (tail != 0) render_tail(tail); }
//************************************************************************ void DrawPartBox(struct L3PartS *PartPtr,int CurColor,float m[4][4],int wire) { float r[4]; int i, Color; float r2[4]; vector3d bb3d[8]; #ifdef SIXTEEN_EDGE_COLORS if (0 <= CurColor && CurColor <= 15) Color = edge_color(CurColor); else Color = 0; #else Color = edge_color(CurColor); #endif Color = CurColor; #if 0 printf("IsModel = %d FromPARTS = %d color = %d\n", IsModel, PartPtr->FromPARTS, Color); printf("BBox = (%0.2f,%0.2f,%0.2f) (%0.2f,%0.2f,%0.2f)\n", PartPtr->BBox[0][0],PartPtr->BBox[0][1],PartPtr->BBox[0][2], PartPtr->BBox[1][0],PartPtr->BBox[1][1],PartPtr->BBox[1][2]); #endif MakePartBox(PartPtr, m, bb3d); if (wire) // Draw wireframe box. { render_line(&bb3d[0],&bb3d[1],Color); render_line(&bb3d[1],&bb3d[2],Color); render_line(&bb3d[2],&bb3d[3],Color); render_line(&bb3d[3],&bb3d[0],Color); render_line(&bb3d[4],&bb3d[5],Color); render_line(&bb3d[5],&bb3d[6],Color); render_line(&bb3d[6],&bb3d[7],Color); render_line(&bb3d[7],&bb3d[4],Color); render_line(&bb3d[0],&bb3d[4],Color); render_line(&bb3d[1],&bb3d[5],Color); render_line(&bb3d[2],&bb3d[6],Color); render_line(&bb3d[3],&bb3d[7],Color); } else // Lets try a solid box. { render_quad(&bb3d[0],&bb3d[1],&bb3d[2],&bb3d[3],Color); render_quad(&bb3d[4],&bb3d[5],&bb3d[6],&bb3d[7],Color); render_quad(&bb3d[0],&bb3d[4],&bb3d[5],&bb3d[1],Color); render_quad(&bb3d[1],&bb3d[5],&bb3d[6],&bb3d[2],Color); render_quad(&bb3d[2],&bb3d[6],&bb3d[7],&bb3d[3],Color); render_quad(&bb3d[3],&bb3d[7],&bb3d[4],&bb3d[0],Color); } }
int renderer_sdl2::draw(int update) { texture_info *texture=nullptr; float vofs, hofs; int blit_pixels = 0; if (video_config.novideo) { return 0; } auto win = assert_window(); osd_dim wdim = win->get_size(); if (has_flags(FI_CHANGED) || (wdim.width() != m_width) || (wdim.height() != m_height)) { destroy_all_textures(); m_width = wdim.width(); m_height = wdim.height(); SDL_RenderSetViewport(m_sdl_renderer, nullptr); m_blittimer = 3; clear_flags(FI_CHANGED); } //SDL_SelectRenderer(window().sdl_window); if (m_blittimer > 0) { /* SDL Underlays need alpha = 0 ! */ SDL_SetRenderDrawBlendMode(m_sdl_renderer, SDL_BLENDMODE_NONE); //SDL_SetRenderDrawColor(0,0,0,255); SDL_SetRenderDrawColor(m_sdl_renderer, 0,0,0,0); SDL_RenderFillRect(m_sdl_renderer, nullptr); m_blittimer--; } // compute centering parameters vofs = hofs = 0.0f; if (video_config.centerv || video_config.centerh) { int ch, cw; ch = wdim.height(); cw = wdim.width(); if (video_config.centerv) { vofs = (ch - m_blit_dim.height()) / 2.0f; } if (video_config.centerh) { hofs = (cw - m_blit_dim.width()) / 2.0f; } } m_last_hofs = hofs; m_last_vofs = vofs; win->m_primlist->acquire_lock(); // now draw for (render_primitive &prim : *win->m_primlist) { Uint8 sr, sg, sb, sa; switch (prim.type) { case render_primitive::LINE: sr = (int)(255.0f * prim.color.r); sg = (int)(255.0f * prim.color.g); sb = (int)(255.0f * prim.color.b); sa = (int)(255.0f * prim.color.a); SDL_SetRenderDrawBlendMode(m_sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim.flags))); SDL_SetRenderDrawColor(m_sdl_renderer, sr, sg, sb, sa); SDL_RenderDrawLine(m_sdl_renderer, prim.bounds.x0 + hofs, prim.bounds.y0 + vofs, prim.bounds.x1 + hofs, prim.bounds.y1 + vofs); break; case render_primitive::QUAD: texture = texture_update(prim); if (texture) blit_pixels += (texture->raw_height() * texture->raw_width()); render_quad(texture, prim, round_nearest(hofs + prim.bounds.x0), round_nearest(vofs + prim.bounds.y0)); break; default: throw emu_fatalerror("Unexpected render_primitive type\n"); } } win->m_primlist->release_lock(); m_last_blit_pixels = blit_pixels; m_last_blit_time = -osd_ticks(); SDL_RenderPresent(m_sdl_renderer); m_last_blit_time += osd_ticks(); return 0; }
static void render_pass(shader_pass *pass, int first, int last) { int output_w = -1; int output_h = -1; debug_printf("\n"); // If the horizontal scale method is fixed, set the output width to // the horizontal scale value. if (pass->hor_scale_method == SCALING_FIXED) { output_w = pass->hor_scale_value; } // If the horizontal scale method is input, set the output width to the // horizontal component of the current input size, multiplied by // the horizontal scale value. else if (pass->hor_scale_method == SCALING_INPUT) { output_w = g_cur_input_w * pass->hor_scale_value; } // If the horizontal scale method is output, set the output width to the // horizontal component of the final output size, multiplied by the // horizontal scale value. else if (pass->hor_scale_method == SCALING_OUTPUT) { output_w = g_final_output_w * pass->hor_scale_value; } // If this is the first shader pass, and the output width is not yet set, // the host application may set the output width to an arbitrary value. else if (first && !last) { output_w = 1024; debug_printf("setting output width to arbitrary value %d\n", output_w); } // If this is the last shader pass: if (last) { // If the output width is already set, set requires implicit // pass to True. if (output_w > 0) { g_requires_implicit_pass = 1; } // If the output width is not yet set, set the output width to // the horizontal component of the final output size. else { output_w = g_final_output_w; } } // Otherwise, set the output width to the horizontal component of // the current input size. if (output_w < 0) { output_w = g_cur_input_w; } // If the vertical scale method is fixed, set the output height to the // vertical scale value. if (pass->ver_scale_method == SCALING_FIXED) { output_h = pass->ver_scale_value; debug_printf("pass->ver_scale_method == SCALING_FIXED, " "output_h = %d\n", output_h); } // If the vertical scale method is input, set the output height to the // vertical component of the current input size, multiplied by the // vertical scale value. else if (pass->ver_scale_method == SCALING_INPUT) { output_h = g_cur_input_h * pass->ver_scale_value; debug_printf("pass->ver_scale_method == SCALING_INPUT, " "output_h = %d\n", output_h); } // If the vertical scale method is output, set the output height to the // vertical component of the final output size, multiplied by the vertical // scale value. else if (pass->ver_scale_method == SCALING_OUTPUT) { output_h = g_final_output_h * pass->ver_scale_value; debug_printf("pass->ver_scale_method == SCALING_OUTPUT, " "output_h = %d\n", output_h); } // If this is the first shader pass, and the output height is not yet // set, the host application may set the output height to an arbitrary // value. else if (first && !last) { output_h = 1024; debug_printf("setting output height to arbitrary value %d\n", output_h); } // If this is the last shader pass: if (last) { // If the output height is already set, set requires implicit pass // to True. if (output_h > 0) { g_requires_implicit_pass = 1; } // If the output height is not yet set, set the output height to // the vertical component of the final output size. else { output_h = g_final_output_h; } } // Otherwise, set the output height to the vertical component of the // current input size. if (output_h < 0) { output_h = g_cur_input_h; } // Calculate the output size by combining the output width and // the output height. // If this is not the last shader pass, or this is the last shader pass // and requires implicit pass is True: GLuint frame_buffer = 0; GLuint output_texture = 0; int output_texture_w = 0; int output_texture_h = 0; //g_requires_implicit_pass = 1; if (!last || g_requires_implicit_pass) { // Construct the output texture with a suitable set of dimensions // larger than the output size. if (!pass->texture) { glGenTextures(1, &pass->texture); CHECK_GL_ERROR(); } output_texture = pass->texture; output_texture_w = round_up_pow2(output_w); output_texture_h = round_up_pow2(output_h); // The following is a hack to fix compatibility with // CRT-interlaced-halation.shader which has a faulty assumption, // that rubyTextureSize and rubyOriginalTextureSize will be the // same in the final pass. The reason they may not be the same is // because of the crop / zoom function, so for example, FS-UAE may // allocate a 1024x1024 texture, but because of cropping, a // 1024x512 will be big enough for subsequent passes. if (output_texture_h < g_orig_texture_h) { output_texture_h = g_orig_texture_h; } if (output_texture_w < g_orig_texture_w) { output_texture_w = g_orig_texture_w; } fs_gl_bind_texture(output_texture); // using RGBA ensures that line size in bytes is a multiple of 4 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, output_texture_w, output_texture_h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); fs_gl_bind_texture(0); // Construct a framebuffer object, and bind the output texture to it // as GL_COLOR_ATTACHMENT0. // Tell OpenGL to render to the frame-buffer object. if (!pass->frame_buffer) { //debug_printf("generating frame buffer\n"); glGenFramebuffers(1, &pass->frame_buffer); CHECK_GL_ERROR(); } frame_buffer = pass->frame_buffer; glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); debug_printf("%d %d\n", output_w, output_h); glViewport(0, 0, output_w, output_h); glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer); CHECK_GL_ERROR(); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, output_texture, 0); CHECK_GL_ERROR(); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { debug_printf("fbo is not complete!\n"); } glClear(GL_COLOR_BUFFER_BIT); } // Set the GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER parameters // of the current texture according to the filter setting in the current // shader pass. //glBindTexture(GL_TEXTURE_2D, g_cur_texture); fs_gl_bind_texture(g_cur_texture); CHECK_GL_ERROR(); if (pass->filtering == FILTERING_NEAREST) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR(); // Tell OpenGL to use the shader program handle from the current shader // pass as the active shader program. glUseProgram(pass->program); CHECK_GL_ERROR(); GLint rubyFrameCount = glGetUniformLocation(pass->program, "rubyFrameCount"); if (rubyFrameCount >= 0) { glUniform1i(rubyFrameCount, g_frame_count); } CHECK_GL_ERROR(); // Set the uniform rubyOrigTexture to the original texture. GLint rubyOrigTexture = glGetUniformLocation(pass->program, "rubyOrigTexture"); if (rubyOrigTexture >= 0) { debug_printf("set rubyOrigTexture to %d\n", 1); glUniform1i(rubyOrigTexture, 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, g_orig_texture); glActiveTexture(GL_TEXTURE0); } CHECK_GL_ERROR(); // Set the uniform rubyOrigTextureSize to the original texture size. GLint rubyOrigTextureSize = glGetUniformLocation(pass->program, "rubyOrigTextureSize"); if (rubyOrigTextureSize >= 0) { debug_printf("set rubyOrigTextureSize to %dx%d\n", g_orig_texture_w, g_orig_texture_h); glUniform2f(rubyOrigTextureSize, g_orig_texture_w, g_orig_texture_h); } CHECK_GL_ERROR(); // Set the uniform rubyOrigInputSize to the original input size. GLint rubyOrigInputSize = glGetUniformLocation(pass->program, "rubyOrigInputSize"); if (rubyOrigInputSize >= 0) { debug_printf("set rubyOrigInputSize to %dx%d\n", g_orig_input_w, g_orig_input_h); glUniform2f(rubyOrigInputSize, g_orig_input_w, g_orig_input_h); } CHECK_GL_ERROR(); // Set the uniform rubyTexture to the current texture. GLint rubyTexture = glGetUniformLocation(pass->program, "rubyTexture"); if (rubyTexture >= 0) { debug_printf("set rubyTexture to %d\n", 0); glUniform1i(rubyTexture, 0); } CHECK_GL_ERROR(); // Set the uniform rubyTextureSize to the current texture size. GLint rubyTextureSize = glGetUniformLocation(pass->program, "rubyTextureSize"); if (rubyTextureSize >= 0) { debug_printf("set rubyTextureSize to %dx%d\n", g_cur_texture_w, g_cur_texture_h); glUniform2f(rubyTextureSize, g_cur_texture_w, g_cur_texture_h); } CHECK_GL_ERROR(); // Set the uniform rubyInputSize to the current input size. GLint rubyInputSize = glGetUniformLocation(pass->program, "rubyInputSize"); if (rubyInputSize >= 0) { debug_printf("set rubyInputSize to %dx%d\n", g_cur_input_w, g_cur_input_h); glUniform2f(rubyInputSize, g_cur_input_w, g_cur_input_h); } CHECK_GL_ERROR(); // Set the uniform rubyOutputSize to the output size. GLint rubyOutputSize = glGetUniformLocation(pass->program, "rubyOutputSize"); if (rubyOutputSize >= 0) { debug_printf("set rubyOutputSize to %dx%d\n", output_w, output_h); glUniform2f(rubyOutputSize, output_w, output_h); } CHECK_GL_ERROR(); // Render a quad, textured with the current texture, with a vertex at // each corner of the output size. float s2 = (float) g_cur_input_w / (float) g_cur_texture_w; float t2 = (float) g_cur_input_h / (float) g_cur_texture_h; fs_gl_bind_texture(g_cur_texture); render_quad(s2, 0.0, t2, first, last && !g_requires_implicit_pass, first); CHECK_GL_ERROR(); // Tell OpenGL not to use a shader program (i.e. glUseProgram(0)). glUseProgram(0); CHECK_GL_ERROR(); // If this is not the last shader pass, or this is the last shader pass // and requires implicit pass is True: if (!last || g_requires_implicit_pass) { // Tell OpenGL not to use the frame-buffer object. debug_printf("unbind framebuffer\n"); glBindFramebuffer(GL_FRAMEBUFFER, 0); CHECK_GL_ERROR(); glViewport(0, 0, fs_ml_video_width(), fs_ml_video_height()); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } // Set the current input size to the current output size. g_cur_input_w = output_w; g_cur_input_h = output_h; // Set the current texture size to the size of the output texture. g_cur_texture_w = output_texture_w; g_cur_texture_h = output_texture_h; // Set the current texture to the output texture. g_cur_texture = output_texture; }
int fs_emu_xml_shader_render(int texture, int texture_width, int texture_height, int input_width, int input_height, int output_width, int output_height, float x1, float y1, float x2, float y2, int render_textured_side, float alpha) { if (!fs_emu_xml_shader_is_enabled()) { return 0; } g_x1 = x1; g_x2 = x2; g_y1 = y1; g_y2 = y2; g_alpha = alpha; g_render_textured_side = render_textured_side; fs_gl_blending(0); fs_gl_texturing(1); fs_gl_color4f(1.0, 1.0, 1.0, 1.0); // Let the current input size be the dimensions of the video-frame // generated by the host application. g_cur_input_w = input_width; g_cur_input_h = input_height; // Calculate the current texture size as a suitable set of dimensions // larger than the current input size. g_cur_texture_w = texture_width; g_cur_texture_h = texture_height; // Calculate the final output size as the dimensions of the region of the // back-buffer where the output will be displayed to the user, measured // in pixels. g_final_output_w = output_width; g_final_output_h = output_height; // Let requires implicit pass be False. g_requires_implicit_pass = 0; // Construct the current texture, whose dimensions are the current // texture size, and draw the video-frame generated by the host // application into it. g_cur_texture = texture; debug_printf("\n\n\n\n\n"); debug_printf("cur tex %d\n", g_cur_texture); g_orig_texture = g_cur_texture; g_orig_texture_w = g_cur_texture_w; g_orig_texture_h = g_cur_texture_h; g_orig_input_w = g_cur_input_w; g_orig_input_h = g_cur_input_h; debug_printf("final output: %d %d\n", g_final_output_w, g_final_output_h); debug_printf(" input: %d %d\n", g_cur_input_w, g_cur_input_h); debug_printf(" texture: %d %d\n", g_cur_texture_w, g_cur_texture_h); // For each shader pass in the list of shader passes... GList *link = g_active_shader->passes; int first = 1; while (link) { shader_pass *pass = link->data; render_pass(pass, first, link->next == NULL); first = 0; link = link->next; } // If requires implicit pass is True if (g_requires_implicit_pass) { debug_printf("implicit pass, cur tex %d %d %d\n", g_cur_texture, g_cur_texture_w, g_cur_texture_h); // Render a quad, textured with the current texture, with a vertex // at each corner of the final output size. float s2 = (float) g_cur_input_w / (float) g_cur_texture_w; float t2 = (float) g_cur_input_h / (float) g_cur_texture_h; fs_gl_bind_texture(g_cur_texture); render_quad(s2, 0.0, t2, 0, 1, 0); } CHECK_GL_ERROR(); g_frame_count++; glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR(); return 1; }
int Draw1PartPtr(struct L3LineS *LinePtr, int Color) { float m1[4][4]; int CurColor = ldraw_commandline_opts.C; int SaveColor; int i; float r[4]; vector3d v3d[4]; if (!LinePtr) return 0; InitViewMatrix(); include_stack_ptr = 1; // Start nesting level pointer at 1. SaveColor = LinePtr->Color; if (Color < 0) Color = LinePtr->Color; else LinePtr->Color = Color; switch (Color) { case 16: Color = CurColor; break; case 24: #ifdef SIXTEEN_EDGE_COLORS if (0 <= CurColor && CurColor <= 15) Color = edge_color(CurColor); else Color = 0; #else Color = edge_color(CurColor); #endif break; default: break; } switch (LinePtr->LineType) { case 0: break; case 1: M4M4Mul(m1,m_m,LinePtr->v); if ((ldraw_commandline_opts.F & TYPE_F_XOR_MODE) && (LinePtr->PartPtr->FromP)) { // This is a primitive and may render invisibly in TYPE_F_XOR_MODE // if it contains no edges. ldraw_commandline_opts.F |= TYPE_F_XOR_PRIMITIVE; DrawPart(0,LinePtr->PartPtr,Color,m1); ldraw_commandline_opts.F &= ~(TYPE_F_XOR_PRIMITIVE); break; } DrawPart(0,LinePtr->PartPtr,Color,m1); break; case 2: for (i=0; i<LinePtr->LineType; i++) { M4V3Mul(r,m_m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } render_line(&v3d[0],&v3d[1],Color); break; case 3: for (i=0; i<LinePtr->LineType; i++) { M4V3Mul(r,m_m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } //if (zWire) if ((ldraw_commandline_opts.F & TYPE_F_NO_POLYGONS) || (ldraw_commandline_opts.F & TYPE_F_XOR_MODE)) { // This would render invisibly in TYPE_F_XOR_MODE // since it contains no edges. render_line(&v3d[0],&v3d[1],Color); render_line(&v3d[1],&v3d[2],Color); render_line(&v3d[2],&v3d[0],Color); break; } render_triangle(&v3d[0],&v3d[1],&v3d[2],Color); break; case 4: for (i=0; i<LinePtr->LineType; i++) { M4V3Mul(r,m_m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } //if (zWire) if ((ldraw_commandline_opts.F & TYPE_F_NO_POLYGONS) || (ldraw_commandline_opts.F & TYPE_F_XOR_MODE)) { // This would render invisibly in TYPE_F_XOR_MODE // since it contains no edges. render_line(&v3d[0],&v3d[1],Color); render_line(&v3d[1],&v3d[2],Color); render_line(&v3d[2],&v3d[3],Color); render_line(&v3d[3],&v3d[0],Color); break; } render_quad(&v3d[0],&v3d[1],&v3d[2],&v3d[3],Color); break; case 5: for (i=0; i<4; i++) { M4V3Mul(r,m_m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } if (ldraw_commandline_opts.F & TYPE_F_XOR_MODE) { render_line(&v3d[0],&v3d[1],Color); render_line(&v3d[0],&v3d[2],Color); render_line(&v3d[1],&v3d[3],Color); break; } render_five(&v3d[0],&v3d[1],&v3d[2],&v3d[3],Color); break; default: break; } LinePtr->Color = SaveColor; return 1; }
static void DrawPart(int IsModel, struct L3PartS *PartPtr, int CurColor, float m[4][4]) { float r[4], m1[4][4]; int i, Color; struct L3LineS *LinePtr; vector3d v3d[4]; #ifdef USE_OPENGL float mm[4][4]; float det = 0; if ((ldraw_commandline_opts.F & TYPE_F_STUDLINE_MODE) != 0) if (PartPtr->IsStud) { DrawPartLine(PartPtr, CurColor, m); //DrawPartBox(PartPtr, CurColor, m, 1); return; } // Draw only bounding boxes of top level parts if in fast spin mode. if (ldraw_commandline_opts.F & TYPE_F_BBOX_MODE) if (PartPtr->FromPARTS) // (!IsModel) { if (ldraw_commandline_opts.F & TYPE_F_NO_POLYGONS) DrawPartBox(PartPtr, CurColor, m, 1); else DrawPartBox(PartPtr, CurColor, m, 0); return; } if (PartPtr->IsStud) det = M3Det(m); // Check the determinant of m to fix mirrored studs. #endif for (LinePtr = PartPtr->FirstLine; LinePtr; LinePtr = LinePtr->NextLine) { #ifdef USE_OPENGL char *s; if (Skip1Line(IsModel,LinePtr)) continue; #endif hardcolor = 0; // Assume color 16 or 24. switch (LinePtr->Color) { case 16: Color = CurColor; break; case 24: #ifdef SIXTEEN_EDGE_COLORS if (0 <= CurColor && CurColor <= 15) Color = edge_color(CurColor); else Color = 0; #else Color = edge_color(CurColor); #endif break; default: Color = LinePtr->Color; #if 0 if ((LinePtr->LineType == 3) || (LinePtr->LineType == 4)) // Hardcoded color = printed. Blend me! hardcolor = 1; #else if (LinePtr->LineType != 1) // Hardcoded color = printed. Blend me! hardcolor = 1; #endif break; } switch (LinePtr->LineType) { case 0: #ifdef USE_OPENGL // Skip whitespace for (s = LinePtr->Comment; *s != 0; s++) { if ((*s != ' ') && (*s != '\t')) break; } if (strnicmp(s,"STEP",4) == 0) { // if (include_stack_ptr <= ldraw_commandline_opts.output_depth ) { zStep(stepcount,1); stepcount++; } } else if (strncmp(s,"CLEAR",5) == 0) { // if (include_stack_ptr <= ldraw_commandline_opts.output_depth ) { zClear(); } } // Experiment with MLCAD extensions // Based on info provided on lugnet. else if (strncmp(s,"BUFEXCHG A STORE",16) == 0) { int k; if (IsModel) { k = BufA1Store(IsModel,LinePtr); printf("BUFEXCHG A STORE %d\n", k); } } else if (strncmp(s,"BUFEXCHG A RETRIEVE",19) == 0) { int j,n, opts, dcp, cp; extern int curpiece; extern int DrawToCurPiece; void DrawModel(void); if (IsModel) { n = BufA1Retrieve(IsModel,LinePtr); printf("BUFEXCHG A RETRIEVE %d\n", n); // clear and redraw model up to saved point. #if 0 opts = ldraw_commandline_opts.M; ldraw_commandline_opts.M = 'C'; dcp = DrawToCurPiece; DrawToCurPiece = 1; cp = curpiece; zClear(); curpiece = n; Init1LineCounter(); BufA1Store(IsModel,LinePtr); DrawModel(); //for(j = 0; j < n; j++) // Draw1Part(j, -1); DrawToCurPiece = dcp; curpiece = cp; ldraw_commandline_opts.M = opts; #endif } } else if (strncmp(s,"GHOST",5) == 0) { if (IsModel) { // Parse the rest of the line as a .DAT line. } } if (ldraw_commandline_opts.M != 'C') { // Non-continuous output stop after each step. } // Parse global color change meta-commands // Should?? be done by ReadMetaLine() in L3Input.cpp // Should SAVE old colors, restore after the for loop. // To save space, build a linked list of saved colors. // Do NOT resave a color if its already saved. if ((strncmp(s,"COLOR",5) == 0) || (strncmp(s,"COLOUR",6) == 0)) { if (ldraw_commandline_opts.debug_level == 1) printf("%s\n", s); //0 COLOR 4 red 0 196 0 38 255 196 0 38 255 char colorstr[256]; char name[256]; int n, inverse_index; n = sscanf(s, "%s %d %s %d %f %f %f %f %f %f %f %f", colorstr, &i, name, &inverse_index, &m1[0][0], &m1[0][1], &m1[0][2], &m1[0][3], &m1[1][0], &m1[1][1], &m1[1][2], &m1[1][3]); if (n != 12) { if (ldraw_commandline_opts.debug_level == 1) printf("Illegal COLOR syntax %d\n",n); break; } zcolor_modify(i,name,inverse_index, (int)m1[0][0], (int)m1[0][1], (int)m1[0][2], (int)m1[0][3], (int)m1[1][0], (int)m1[1][1], (int)m1[1][2], (int)m1[1][3]); } // Intercept the ldconfig.ldr !COLOUR meta command. if (ldlite_parse_colour_meta(s)) break; #else if (strncmp(LinePtr->Comment,"STEP",4) == 0) { // STEP encountered, you may set some flags to enable/disable e.g. drawing // (Note that I have not tested this, but this is the way it is supposed to work :-) } #endif break; case 1: #ifdef USE_OPENGL // NOTE: I could achieve L3Lab speeds if I delay rendering studs till last // then do occlusion tests on the bounding boxes before rendering. // Unfortunately GL_OCCLUSION_TEST_HP is an extension (SUN, HP, ???) // // Other ideas include substituting GLU cylinder primitives for studs. if (LinePtr->PartPtr->IsStud) { if ((ldraw_commandline_opts.F & TYPE_F_STUDLESS_MODE) != 0) break; #ifdef USE_OPENGL_OCCLUSION if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) != 0) { M4M4Mul(m1,m,LinePtr->v); if (Occluded(LinePtr->PartPtr, Color, m1)) break; } #endif } #endif M4M4Mul(m1,m,LinePtr->v); #ifdef USE_OPENGL // Negative determinant means its a mirrored stud. if (det < 0) { // For now, we only support Paul Easters logo.dat texture. // For display speed, we really should precalculate an IsLogo flag // and use that here rather than IsStud. if (LinePtr->PartPtr && LinePtr->PartPtr->DatName && !stricmp(LinePtr->PartPtr->DatName, "logo.dat")) { float mirror[4][4] = { {1.0,0.0,0.0,0.0}, {0.0,1.0,0.0,0.0}, {0.0,0.0,-1.0,0.0}, {0.0,0.0,0.0,1.0} }; M4M4Mul(mm,m1,mirror); memcpy(m1,mm,sizeof(m1)); } } // implement nesting level counter. include_stack_ptr++; DrawPart(0,LinePtr->PartPtr,Color,m1); include_stack_ptr--; // Do zStep() after the model, not toplevel parts. #else DrawPart(0,LinePtr->PartPtr,Color,m1); if (IsModel) zStep(0,0); #endif break; case 2: #ifdef USE_OPENGL_OCCLUSION if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) && !(PartPtr->IsStud)) break; #endif for (i=0; i<LinePtr->LineType; i++) { M4V3Mul(r,m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } render_line(&v3d[0],&v3d[1],Color); break; case 3: #ifdef USE_OPENGL_OCCLUSION if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) && !(PartPtr->IsStud)) break; #endif for (i=0; i<LinePtr->LineType; i++) { M4V3Mul(r,m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } #ifdef USE_OPENGL // Try to render solid Primitives visibly when in XOR wire mode. if (ldraw_commandline_opts.F & TYPE_F_XOR_PRIMITIVE) { render_line(&v3d[0],&v3d[1],Color); render_line(&v3d[1],&v3d[2],Color); render_line(&v3d[2],&v3d[0],Color); break; } #endif render_triangle(&v3d[0],&v3d[1],&v3d[2],Color); break; case 4: #ifdef USE_OPENGL_OCCLUSION if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) && !(PartPtr->IsStud)) break; #endif for (i=0; i<LinePtr->LineType; i++) { M4V3Mul(r,m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } #ifdef USE_OPENGL // Try to render solid Primitives visibly when in XOR wire mode. if (ldraw_commandline_opts.F & TYPE_F_XOR_PRIMITIVE) { render_line(&v3d[0],&v3d[1],Color); render_line(&v3d[1],&v3d[2],Color); render_line(&v3d[2],&v3d[3],Color); render_line(&v3d[3],&v3d[0],Color); break; } #endif render_quad(&v3d[0],&v3d[1],&v3d[2],&v3d[3],Color); break; case 5: #ifdef USE_OPENGL_OCCLUSION if ((ldraw_commandline_opts.F & TYPE_F_STUDONLY_MODE) && !(PartPtr->IsStud)) break; #endif for (i=0; i<4; i++) { M4V3Mul(r,m,LinePtr->v[i]); v3d[i].x=r[0]; v3d[i].y=r[1]; v3d[i].z=r[2]; } render_five(&v3d[0],&v3d[1],&v3d[2],&v3d[3],Color); break; } } if (((zDetailLevel == TYPE_PART) && (PartPtr->FromPARTS)) || ((zDetailLevel == TYPE_P) && (PartPtr->FromP))) zStep(-1, 0); }
static int draw13_window_draw(sdl_window_info *window, UINT32 dc, int update) { sdl_info *sdl = (sdl_info *) window->dxdata; render_primitive *prim; texture_info *texture=NULL; float vofs, hofs; int blit_pixels = 0; if (video_config.novideo) { return 0; } if (sdl->resize_pending) { SDL_SetWindowSize(window->sdl_window, sdl->resize_width, sdl->resize_height); SDL_GetWindowSize(window->sdl_window, &window->width, &window->height); sdl->resize_pending = 0; SDL_RenderSetViewport(sdl->sdl_renderer, NULL); } //SDL_SelectRenderer(window->sdl_window); if (sdl->blittimer > 0) { /* SDL Underlays need alpha = 0 ! */ SDL_SetRenderDrawBlendMode(sdl->sdl_renderer, SDL_BLENDMODE_NONE); //SDL_SetRenderDrawColor(0,0,0,255); SDL_SetRenderDrawColor(sdl->sdl_renderer, 0,0,0,0); SDL_RenderFillRect(sdl->sdl_renderer, NULL); sdl->blittimer--; } // compute centering parameters vofs = hofs = 0.0f; if (video_config.centerv || video_config.centerh) { int ch, cw; if ((window->fullscreen) && (!video_config.switchres)) { ch = window->monitor->center_height; cw = window->monitor->center_width; } else { ch = window->height; cw = window->width; } if (video_config.centerv) { vofs = (ch - window->blitheight) / 2.0f; } if (video_config.centerh) { hofs = (cw - window->blitwidth) / 2.0f; } } sdl->last_hofs = hofs; sdl->last_vofs = vofs; window->primlist->acquire_lock(); // now draw for (prim = window->primlist->first(); prim != NULL; prim = prim->next()) { Uint8 sr, sg, sb, sa; switch (prim->type) { case render_primitive::LINE: sr = (int)(255.0f * prim->color.r); sg = (int)(255.0f * prim->color.g); sb = (int)(255.0f * prim->color.b); sa = (int)(255.0f * prim->color.a); SDL_SetRenderDrawBlendMode(sdl->sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim->flags))); SDL_SetRenderDrawColor(sdl->sdl_renderer, sr, sg, sb, sa); SDL_RenderDrawLine(sdl->sdl_renderer, prim->bounds.x0 + hofs, prim->bounds.y0 + vofs, prim->bounds.x1 + hofs, prim->bounds.y1 + vofs); break; case render_primitive::QUAD: texture = texture_update(window, prim); if (texture) blit_pixels += (texture->rawheight * texture->rawwidth); render_quad(sdl, texture, prim, round_nearest(hofs + prim->bounds.x0), round_nearest(vofs + prim->bounds.y0)); break; default: throw emu_fatalerror("Unexpected render_primitive type\n"); } } window->primlist->release_lock(); sdl->last_blit_pixels = blit_pixels; sdl->last_blit_time = -osd_ticks(); SDL_RenderPresent(sdl->sdl_renderer); sdl->last_blit_time += osd_ticks(); return 0; }