X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fnogl%2FnoGLALSW.inc;h=bec8350941184b5f5453209c1d24a4a9cc462864;hb=fe8b553e08f76cf35cba0a0e149140db87aa71c6;hp=55ee112fe1bfbd05dfcd820cefca48fd799b9f34;hpb=ed750d2e31615702f9c230ef4aabe890ea55abab;p=d2df-sdl.git diff --git a/src/nogl/noGLALSW.inc b/src/nogl/noGLALSW.inc index 55ee112..bec8350 100644 --- a/src/nogl/noGLALSW.inc +++ b/src/nogl/noGLALSW.inc @@ -11,6 +11,12 @@ implementation ValPerCoord = 2; StackSize = 16; + BLEND_BLEND = 0; + BLEND_DARKER = 1; + BLEND_FILTER = 2; + BLEND_INVERT = 3; + BLEND_DEFAULT = 5; + type TArrayFloat = array of GLfloat; TArrayInteger = array of Integer; @@ -34,14 +40,25 @@ implementation ccol: Integer; clearColor: cint; stack: array [0..StackSize - 1] of record - x, y: Integer; + x, y, a: Integer; end; stack_ptr: Integer; + vpx, vpy: Integer; + pointSize: Integer; + matrixMode: GLenum; + blendMode: Integer; + + globalTransTable: COLOR_MAP_T; + redTransTable: COLOR_MAP_T; + greenTransTable: COLOR_MAP_T; + blueTransTable: COLOR_MAP_T; + darkTransTable: COLOR_MAP_T; + lightTransTable: COLOR_MAP_T; function AddTexture: Integer; var i: Integer; begin - for i := 0 to High(tex) do + for i := 1 to High(tex) do if not tex[i].used then begin tex[i].used := true; @@ -60,7 +77,7 @@ implementation begin assert(i >= 0); assert(i <= High(tex)); - assert(tex[i].used); + assert((i = 0) or tex[i].used); (* free unallocated texture *) tex[i].used := false; if tex[i].bmp <> nil then destroy_bitmap(tex[i].bmp); @@ -100,7 +117,10 @@ implementation function glGetString(name: GLenum): PChar; begin - result := '' + if name = GL_EXTENSIONS then (* separated by space *) + result := 'GL_ARB_texture_non_power_of_two' + else + result := nil end; procedure glClearColor(red, green, blue, alpha: GLclampf); @@ -120,14 +140,91 @@ implementation procedure glBlendFunc(sfactor, dfactor: GLenum); begin + if (sfactor = GL_SRC_ALPHA) and (dfactor = GL_ONE) then blendMode := BLEND_BLEND + else if (sfactor = GL_ZERO) and (dfactor = GL_SRC_ALPHA) then blendMode := BLEND_DARKER + else if (sfactor = GL_DST_COLOR) and (dfactor = GL_SRC_COLOR) then blendMode := BLEND_FILTER + else if (sfactor = GL_ONE_MINUS_DST_COLOR) and (dfactor = GL_ZERO) then blendMode := BLEND_INVERT + else if (sfactor = GL_SRC_ALPHA) and (dfactor = GL_ONE_MINUS_SRC_ALPHA) then blendMode := BLEND_DEFAULT + else ASSERT(FALSE) + end; + + procedure SetupBlendColor (col: cint); + var r, g, b, a: cint; + begin + //set_trans_blender(r, g, b, a); + //set_add_blender(r, g, b, a); + //set_burn_blender(r, g, b, a); + //set_color_blender(r, g, b, a); + //set_difference_blender(r, g, b, a); + //set_dissolve_blender(r, g, b, a); + //set_dodge_blender(r, g, b, a); + //set_hue_blender(r, g, b, a); + //set_invert_blender(r, g, b, a); + //set_luminance_blender(r, g, b, a); + //set_multiply_blender(r, g, b, a); + //set_saturation_blender(r, g, b, a); + //set_screen_blender(r, g, b, a); + r := getr(col); + g := getg(col); + b := getb(col); + a := geta(col); + color_map := @globalTransTable; + case blendMode of + BLEND_BLEND: + begin + color_map := @lightTransTable; + set_add_blender(r, g, b, a); + drawing_mode(DRAW_MODE_TRANS, nil, 0, 0) + end; + BLEND_DARKER: + begin + color_map := @darkTransTable; + set_multiply_blender(0, 0, 0, 255 - a); + drawing_mode(DRAW_MODE_TRANS, nil, 0, 0) + end; + BLEND_FILTER: + begin + set_luminance_blender(0, 0, 0, 255); + if r <> 0 then + color_map := @redTransTable + else if g <> 0 then + color_map := @greenTransTable + else if b <> 0 then + color_map := @blueTransTable; + drawing_mode(DRAW_MODE_TRANS, nil, 0, 0) + end; + BLEND_INVERT: + begin + drawing_mode(DRAW_MODE_XOR, nil, 0, 0) + end; + BLEND_DEFAULT: + begin + (* FIX texture colorize *) + if DEFAULT_DEPTH <= 8 then + begin + drawing_mode(DRAW_MODE_SOLID, nil, 0, 0) + end + else + begin + set_color_blender(0, 0, 0, 0); + drawing_mode(DRAW_MODE_TRANS, nil, 0, 0) + end + end + else + ASSERT(FALSE) + end end; procedure glPointSize(size: GLfloat); begin + ASSERT(size >= 0); + if size <= 1.0 then pointSize := ceil(size) + else pointSize := floor(size) end; procedure glLineWidth(width: GLfloat); begin + (* width > 1 used in rare cases, not critical *) end; procedure glGetIntegerv(pname: GLenum; params: PGLint); @@ -155,34 +252,67 @@ implementation procedure glEnd; var - i, j, k, w, h, x0, y0, x1, y1, offx, offy, tmp, s0, t0, s1, t1: Integer; + i, j, k, w, h, x0, y0, x1, y1, offx, offy, tmp, s0, t0, s1, t1, angle: Integer; oldx0, oldy0, oldx1, oldy1: cint; flipv, fliph: Boolean; draw_sprite_proc: procedure (bmp, sprite: Allegro.PBITMAP; x, y: cint); cdecl; + rotate_sprite_proc: procedure (bmp, sprite: Allegro.PBITMAP; x, y: cint; a: cint32); cdecl; begin assert(cmds.mode <> GL_INVALID_ENUM); assert(Length(cmds.v) mod ValPerVertex = 0); assert(Length(cmds.c) mod ValPerColor = 0); assert(Length(cmds.t) mod ValPerCoord = 0); - offx := stack[stack_ptr].x; - offy := stack[stack_ptr].y; + offx := vpx + stack[stack_ptr].x; + offy := vpy + stack[stack_ptr].y; + angle := stack[stack_ptr].a; + + drawing_mode(DRAW_MODE_SOLID, nil, 0, 0); case cmds.mode of GL_POINTS: begin - (* implement case for texture coords? *) - if Length(cmds.c) <> 0 then - begin - assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *) - for i := 0 to Length(cmds.v) div 2 - 1 do - putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], cmds.c[i]) - end - else - begin - for i := 0 to Length(cmds.v) div 2 - 1 do - putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], ccol) - end + (* implement case for texture coords? *) + if pointSize = 1 then + begin + if Length(cmds.c) <> 0 then + begin + assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *) + for i := 0 to Length(cmds.v) div 2 - 1 do + putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], cmds.c[i]) + end + else + begin + for i := 0 to Length(cmds.v) div 2 - 1 do + putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], ccol) + end + end + else if pointSize > 1 then + begin + x0 := offx - pointSize div 2; + y0 := offy - pointSize div 2; + x1 := offx - (pointSize - 1) div 2; + y1 := offy - (pointSize - 1) div 2; + if Length(cmds.c) <> 0 then + begin + assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *) + for i := 0 to Length(cmds.v) div 2 - 1 do + begin + w := cmds.v[i * 2 + 0]; + h := cmds.v[i * 2 + 1]; + rectfill(sdl2allegro_screen, x0 + w, y0 + h, x1 + w, y1 + h, cmds.c[i]) + end + end + else + begin + for i := 0 to Length(cmds.v) div 2 - 1 do + begin + w := cmds.v[i * 2 + 0]; + h := cmds.v[i * 2 + 1]; + rectfill(sdl2allegro_screen, x0 + w, y0 + h, x1 + w, y1 + h, ccol) + end + end + end end; GL_LINES: begin @@ -241,14 +371,27 @@ implementation tmp := s0; s0 := s1; s1 := tmp; - fliph := not fliph + fliph := not fliph; end; if t1 < t0 then begin tmp := t0; t0 := t1; t1 := tmp; - flipv := not flipv + flipv := not flipv; + end; + + if fliph then + begin + tmp := s0; + s0 := w - s1; + s1 := w - tmp; + end; + if flipv then + begin + tmp := t0; + t0 := h - t1; + t1 := h - tmp; end; s0 := s0 mod w; @@ -265,14 +408,28 @@ implementation else draw_sprite_proc := Allegro.draw_sprite; + if flipv and fliph then + rotate_sprite_proc := Allegro.rotate_sprite_v_flip (* ??? *) + else if flipv then + rotate_sprite_proc := Allegro.rotate_sprite_v_flip + else if fliph then + rotate_sprite_proc := Allegro.rotate_sprite (* ??? *) + else + rotate_sprite_proc := Allegro.rotate_sprite; + oldx0 := 0; oldy0 := 0; oldx1 := 0; oldy1 := 0; get_clip_rect(sdl2allegro_screen, oldx0, oldy0, oldx1, oldy1); set_clip_rect(sdl2allegro_screen, max(oldx0, offx + x0), max(oldy0, offy + y0), min(oldx1, offx + x1), min(oldy1, offy + y1)); - for j := 0 to (y1 - y0 + h - 1) div h - 1 do - for k := 0 to (x1 - x0 + w - 1) div w - 1 do - draw_sprite_proc(sdl2allegro_screen, tex[ctex].bmp, offx + x0 + k * w - s0, offy + y0 + j * h - t0); - //blit(tex[ctex].bmp, sdl2allegro_screen, 0, 0, offx + x0 + k * w - s0, offy + y0 + j * h - t0, w, h); + SetupBlendColor(ccol); + if angle = 0 then + for j := 0 to (y1 - y0 + h - 1) div h - 1 do + for k := 0 to (x1 - x0 + w - 1) div w - 1 do + draw_sprite_proc(sdl2allegro_screen, tex[ctex].bmp, offx + x0 + k * w - s0, offy + y0 + j * h - t0) + else + for j := 0 to (y1 - y0 + h - 1) div h - 1 do + for k := 0 to (x1 - x0 + w - 1) div w - 1 do + rotate_sprite_proc(sdl2allegro_screen, tex[ctex].bmp, offx + x0 + k * w - s0, offy + y0 + j * h - t0, angle); set_clip_rect(sdl2allegro_screen, oldx0, oldy0, oldx1, oldy1); @@ -284,10 +441,14 @@ implementation begin assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *) for i := 0 to Length(cmds.v) div 8 - 1 do + begin + SetupBlendColor(cmds.c[i * 4]); rectfill(sdl2allegro_screen, offx + cmds.v[i * 8], offy + cmds.v[i * 8 + 1], offx + cmds.v[i * 8 + 4], offy + cmds.v[i * 8 + 5], cmds.c[i * 4]) + end end else begin + SetupBlendColor(ccol); for i := 0 to Length(cmds.v) div 8 - 1 do rectfill(sdl2allegro_screen, offx + cmds.v[i * 8], offy + cmds.v[i * 8 + 1], offx + cmds.v[i * 8 + 4], offy + cmds.v[i * 8 + 5], ccol) end @@ -350,58 +511,89 @@ implementation procedure glLoadIdentity; begin + if matrixMode <> GL_MODELVIEW then Exit; with stack[stack_ptr] do begin x := 0; y := 0; + (* TODO Rotation and scale *) end end; procedure glMatrixMode(mode: GLenum); begin + (* GL_PROJECTION -> verify or ignore *) + (* GL_MODELVIEW -> apply *) + ASSERT((mode = GL_PROJECTION) or (mode = GL_MODELVIEW)); + matrixMode := mode; end; procedure glLoadMatrixd(const m: PGLdouble); begin - //m[x,y] + if matrixMode <> GL_MODELVIEW then Exit; + + (* + e_LogWritefln('glLoadMatrix:', []); + e_LogWritefln('| %s %s %s %s |', [m[0], m[1], m[2], m[3]]); + e_LogWritefln('| %s %s %s %s |', [m[4], m[5], m[6], m[7]]); + e_LogWritefln('| %s %s %s %s |', [m[8], m[9], m[10], m[11]]); + e_LogWritefln('| %s %s %s %s |', [m[12], m[13], m[14], m[15]]); + *) + with stack[stack_ptr] do + begin + x := Trunc(m[3]); + y := Trunc(m[7]); + ASSERT(m[11] = 0); + (* TODO Rotation and Scale *) + end end; procedure glPushMatrix; begin + if matrixMode <> GL_MODELVIEW then Exit; stack[stack_ptr + 1] := stack[stack_ptr]; INC(stack_ptr); end; procedure glPopMatrix; begin + if matrixMode <> GL_MODELVIEW then Exit; DEC(stack_ptr) end; procedure glTranslatef(x, y, z: GLfloat); begin + if matrixMode <> GL_MODELVIEW then Exit; ASSERT(z = 0); (* 3D not supported *) - stack[stack_ptr].x := Trunc(x); - stack[stack_ptr].y := Trunc(y); + stack[stack_ptr].x += Trunc(x); + stack[stack_ptr].y += Trunc(y); end; procedure glRotatef(angle, x, y, z: GLfloat); begin - //ASSERT(z = 0); (* 3D not supported *) - (* TODO Rotation *) + if matrixMode <> GL_MODELVIEW then Exit; + ASSERT(x = 0); (* 3D not supported *) + ASSERT(y = 0); (* 3D not supported *) + // angle 360deg == 256 with conversion to fixed point 16.16 + stack[stack_ptr].a += floor(angle * z * 0.71111) * 65536 end; procedure glScalef(x, y, z: GLfloat); begin - //ASSERT(z = 1); (* 3D not supported *) + if matrixMode <> GL_MODELVIEW then Exit; + (* 3D not supported, but z can be any *) (* TODO Scale *) end; procedure glViewport(x, y: GLint; width, height: GLsizei); begin + vpx := x; vpy := y; + set_clip_rect(sdl2allegro_screen, x, y, x + width, y + height); end; procedure glScissor(x, y: GLint; width, height: GLsizei); begin + //set_clip_rect(sdl2allegro_screen, x, y, width, height) end; procedure glStencilMask(mask: GLuint); @@ -446,7 +638,7 @@ implementation end; procedure glTexImage2D(target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); - var i, j, adr: Integer; p: PByte; color: cint; + var i, j, adr: Integer; p: PByte; color, trans: cint; begin assert(target = GL_TEXTURE_2D); assert(level = 0); @@ -461,10 +653,7 @@ implementation if tex[ctex].bmp <> nil then destroy_bitmap(tex[ctex].bmp); - // Video bitmap can lead to bad textures under dos - //tex[ctex].bmp := create_video_bitmap(width, height); - //if tex[ctex].bmp = nil then - tex[ctex].bmp := create_system_bitmap(width, height); + tex[ctex].bmp := create_system_bitmap(width, height); if tex[ctex].bmp = nil then tex[ctex].bmp := create_bitmap(width, height); assert(tex[ctex].bmp <> nil); @@ -474,12 +663,17 @@ implementation p := pixels; if format = GL_RGBA then begin + if DEFAULT_DEPTH <= 8 then + trans := 0 + else + trans := makeacol(255, 0, 255, 0); + for j := 0 to height - 1 do for i := 0 to width - 1 do begin adr := j * width * 4 + i * 4; - if p[adr + 3] <> $FF then - color := 0 + if p[adr + 3] = 0 then + color := trans else color := makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]); putpixel(tex[ctex].bmp, i, j, color) @@ -497,7 +691,7 @@ implementation end; procedure glTexSubImage2D(target: GLenum; level, xoffset, yoffset: GLint; width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); - var i, j, adr: Integer; p: PByte; color: Cint; + var i, j, adr: Integer; p: PByte; color, trans: Cint; begin assert(target = GL_TEXTURE_2D); assert(level = 0); @@ -516,12 +710,17 @@ implementation p := pixels; if format = GL_RGBA then begin + if DEFAULT_DEPTH <= 8 then + trans := 0 + else + trans := makeacol(255, 0, 255, 0); + for j := 0 to height - 1 do for i := 0 to width - 1 do begin adr := j * width * 4 + i * 4; - if p[adr + 3] <> $FF then - color := 0 + if p[adr + 3] = 0 then + color := trans else color := makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]); putpixel(tex[ctex].bmp, i, j, color) @@ -547,7 +746,14 @@ implementation procedure nogl_Init; begin - cmds.mode := GL_INVALID_ENUM + cmds.mode := GL_INVALID_ENUM; + create_trans_table(@globalTransTable, default_palette, 255, 255, 255, nil); + create_trans_table(@redTransTable, default_palette, 0, 255, 255, nil); + create_trans_table(@greenTransTable, default_palette, 255, 0, 255, nil); + create_trans_table(@blueTransTable, default_palette, 255, 255, 0, nil); + create_trans_table(@darkTransTable, default_palette, 191, 191, 191, nil); + create_trans_table(@lightTransTable, default_palette, 64, 64, 64, nil); + color_map := @globalTransTable; end; procedure nogl_Quit;