Пример #1
0
 protected internal virtual void copy(BaseRenderer from)
 {
     imageWriterSkipEOL  = from.imageWriterSkipEOL;
     depthWriterSkipEOL  = from.depthWriterSkipEOL;
     compiledRendererKey = from.compiledRendererKey;
     compiledRenderer    = from.compiledRenderer;
     lighting            = from.lighting;
     textureAccess       = from.textureAccess;
     transform2D         = from.transform2D;
     nearZ                   = from.nearZ;
     farZ                    = from.farZ;
     scissorX1               = from.scissorX1;
     scissorY1               = from.scissorY1;
     scissorX2               = from.scissorX2;
     scissorY2               = from.scissorY2;
     cachedTexture           = from.cachedTexture;
     isTriangle              = from.isTriangle;
     colorTestRef            = from.colorTestRef;
     colorTestMsk            = from.colorTestMsk;
     alphaRef                = from.alphaRef;
     alphaMask               = from.alphaMask;
     stencilRef              = from.stencilRef;
     stencilMask             = from.stencilMask;
     sfix                    = from.sfix;
     dfix                    = from.dfix;
     colorMask               = from.colorMask;
     primaryColorSetGlobally = from.primaryColorSetGlobally;
     texTranslateX           = from.texTranslateX;
     texTranslateY           = from.texTranslateY;
     texScaleX               = from.texScaleX;
     texScaleY               = from.texScaleY;
     textureWidth            = from.textureWidth;
     textureHeight           = from.textureHeight;
     texEnvColorB            = from.texEnvColorB;
     texEnvColorG            = from.texEnvColorG;
     texEnvColorR            = from.texEnvColorR;
     envMapLightPosU         = from.envMapLightPosU;
     envMapLightPosV         = from.envMapLightPosV;
     envMapDiffuseLightU     = from.envMapDiffuseLightU;
     envMapDiffuseLightV     = from.envMapDiffuseLightV;
     envMapShininess         = from.envMapShininess;
     texMinFilter            = from.texMinFilter;
     texMagFilter            = from.texMagFilter;
     primaryColor            = from.primaryColor;
     ditherMatrix            = from.ditherMatrix;
 }
Пример #2
0
        private LongLongKey getBaseRendererKey(GeContext context)
        {
            LongLongKey key = new LongLongKey();

            key.addKeyComponent(RuntimeContext.hasMemoryInt());
            key.addKeyComponent(transform2D);
            key.addKeyComponent(clearMode);
            if (clearMode)
            {
                key.addKeyComponent(context.clearModeColor);
                key.addKeyComponent(context.clearModeStencil);
                key.addKeyComponent(context.clearModeDepth);
            }
            else
            {
                key.addKeyComponent(false);
                key.addKeyComponent(false);
                key.addKeyComponent(false);
            }
            key.addKeyComponent(nearZ == 0x0000);
            key.addKeyComponent(farZ == 0xFFFF);

            key.addKeyComponent(context.colorTestFlag.Enabled ? context.colorTestFunc : GeCommands.CTST_COLOR_FUNCTION_ALWAYS_PASS_PIXEL, 2);

            if (context.alphaTestFlag.Enabled)
            {
                key.addKeyComponent(context.alphaFunc, 3);
                key.addKeyComponent(context.alphaRef == 0x00);
                key.addKeyComponent(context.alphaRef == 0xFF);
            }
            else
            {
                key.addKeyComponent(GeCommands.ATST_ALWAYS_PASS_PIXEL, 3);
                key.addKeyComponent(false);
                key.addKeyComponent(false);
            }

            if (context.stencilTestFlag.Enabled)
            {
                key.addKeyComponent(context.stencilFunc, 3);
                key.addKeyComponent(context.stencilOpFail, 3);
                key.addKeyComponent(context.stencilOpZFail, 3);
                key.addKeyComponent(context.stencilOpZPass, 3);
            }
            else
            {
                key.addKeyComponent(GeCommands.STST_FUNCTION_ALWAYS_PASS_STENCIL_TEST, 3);
                // Use invalid stencil operations
                key.addKeyComponent(7, 3);
                key.addKeyComponent(7, 3);
                key.addKeyComponent(7, 3);
            }

            key.addKeyComponent(context.depthTestFlag.Enabled ? context.depthFunc : GeCommands.ZTST_FUNCTION_ALWAYS_PASS_PIXEL, 3);

            if (context.blendFlag.Enabled)
            {
                key.addKeyComponent(context.blendEquation, 3);
                key.addKeyComponent(context.blend_src, 4);
                key.addKeyComponent(context.blend_dst, 4);
                key.addKeyComponent(context.sfix == 0x000000);
                key.addKeyComponent(context.sfix == 0xFFFFFF);
                key.addKeyComponent(context.dfix == 0x000000);
                key.addKeyComponent(context.dfix == 0xFFFFFF);
            }
            else
            {
                // Use an invalid blend equation value
                key.addKeyComponent(7, 3);
                key.addKeyComponent(15, 4);
                key.addKeyComponent(15, 4);
                key.addKeyComponent(false);
                key.addKeyComponent(false);
                key.addKeyComponent(false);
                key.addKeyComponent(false);
            }

            key.addKeyComponent(context.colorLogicOpFlag.Enabled ? context.logicOp : GeCommands.LOP_COPY, 4);

            key.addKeyComponent(PixelColor.getColor(context.colorMask) == 0x00000000);
            key.addKeyComponent(context.depthMask);
            key.addKeyComponent(context.textureFlag.Enabled);
            key.addKeyComponent(useVertexTexture);
            key.addKeyComponent(context.lightingFlag.Enabled);
            key.addKeyComponent(setVertexPrimaryColor);
            key.addKeyComponent(primaryColorSetGlobally);
            key.addKeyComponent(isTriangle);
            key.addKeyComponent(context.mat_flags, 3);
            key.addKeyComponent(context.useVertexColor);
            key.addKeyComponent(context.textureColorDoubled);
            key.addKeyComponent(context.lightMode, 1);
            key.addKeyComponent(context.tex_map_mode, 2);
            if (context.tex_map_mode == GeCommands.TMAP_TEXTURE_MAP_MODE_TEXTURE_MATRIX)
            {
                key.addKeyComponent(context.tex_proj_map_mode, 2);
            }
            else
            {
                key.addKeyComponent(0, 2);
            }
            key.addKeyComponent(context.tex_translate_x == 0f);
            key.addKeyComponent(context.tex_translate_y == 0f);
            key.addKeyComponent(context.tex_scale_x == 1f);
            key.addKeyComponent(context.tex_scale_y == 1f);
            key.addKeyComponent(context.tex_wrap_s, 1);
            key.addKeyComponent(context.tex_wrap_t, 1);
            key.addKeyComponent(context.textureFunc, 3);
            key.addKeyComponent(context.textureAlphaUsed);
            key.addKeyComponent(context.psm, 2);
            key.addKeyComponent(context.tex_min_filter, 3);
            key.addKeyComponent(context.tex_mag_filter, 1);
            key.addKeyComponent(isLogTraceEnabled);
            key.addKeyComponent(DurationStatistics.collectStatistics);
            key.addKeyComponent(context.ditherFlag.Enabled);

            return(key);
        }
Пример #3
0
        protected internal virtual void initRendering(GeContext context)
        {
            if (renderingInitialized)
            {
                return;
            }

            fbp           = getFrameBufferAddress(context.fbp);
            psm           = context.psm;
            zbp           = getFrameBufferAddress(context.zbp);
            colorTestRef  = getColorBGR(context.colorTestRef);
            colorTestMsk  = getColorBGR(context.colorTestMsk);
            alphaRef      = context.alphaRef & context.alphaMask;
            alphaMask     = context.alphaMask;
            stencilRef    = context.stencilRef & context.stencilMask;
            stencilMask   = context.stencilMask;
            sfix          = context.sfix;
            dfix          = context.dfix;
            colorMask     = getColor(context.colorMask);
            textureWidth  = context.texture_width[mipmapLevel];
            textureHeight = context.texture_height[mipmapLevel];
            texEnvColorB  = getColor(context.tex_env_color[2]);
            texEnvColorG  = getColor(context.tex_env_color[1]);
            texEnvColorR  = getColor(context.tex_env_color[0]);
            texMinFilter  = context.tex_min_filter;
            texMagFilter  = context.tex_mag_filter;
            primaryColor  = getColor(context.vertexColor);

            baseRendererKey = getBaseRendererKey(context);

            if (!transform2D && context.lightingFlag.Enabled)
            {
                lighting = new Lighting(context.view_uploaded_matrix, context.mat_emissive, context.ambient_light, context.lightFlags, context.light_pos, context.light_kind, context.light_type, context.lightAmbientColor, context.lightDiffuseColor, context.lightSpecularColor, context.lightConstantAttenuation, context.lightLinearAttenuation, context.lightQuadraticAttenuation, context.spotLightCutoff, context.spotLightCosCutoff, context.light_dir, context.spotLightExponent, context.materialShininess, context.lightMode, context.vinfo.normal != 0);
            }

            // Is the lighting model using the material color from the vertex color?
            if (!transform2D && context.lightingFlag.Enabled && context.mat_flags != 0 && context.useVertexColor && context.vinfo.color != 0 && isTriangle)
            {
                setVertexPrimaryColor = true;
            }

            primaryColorSetGlobally = false;
            if (transform2D || !context.lightingFlag.Enabled)
            {
                // No lighting, take the primary color from the vertex.
                // This will be done by the BasePrimitiveRenderer when the vertices are known.
                if (context.useVertexColor && context.vinfo.color != 0)
                {
                    setVertexPrimaryColor = true;
                    if (!isTriangle)
                    {
                        // Use the color of the 2nd sprite vertex
                        primaryColorSetGlobally = true;
                    }
                }
                else
                {
                    // Use context.vertexColor as the primary color
                    primaryColorSetGlobally = true;
                }
            }

            textureAccess = null;
            if (isUsingTexture(context))
            {
                int textureBufferWidth = VideoEngine.alignBufferWidth(context.texture_buffer_width[mipmapLevel], context.texture_storage);
                int textureHeight      = context.texture_height[mipmapLevel];
                int textureAddress     = context.texture_base_pointer[mipmapLevel];
                if (cachedTexture == null)
                {
                    int[]   clut32 = VideoEngine.Instance.readClut32(mipmapLevel);
                    short[] clut16 = VideoEngine.Instance.readClut16(mipmapLevel);
                    // Always request the whole buffer width
                    IMemoryReader imageReader = ImageReader.getImageReader(textureAddress, textureBufferWidth, textureHeight, textureBufferWidth, context.texture_storage, context.texture_swizzle, context.tex_clut_addr, context.tex_clut_mode, context.tex_clut_num_blocks, context.tex_clut_start, context.tex_clut_shift, context.tex_clut_mask, clut32, clut16);
                    textureAccess = new RandomTextureAccessReader(imageReader, textureBufferWidth, textureHeight);
                }
                else
                {
                    textureAccess = cachedTexture.OriginalTexture;
                }

                // Avoid an access outside the texture area
                textureAccess = TextureClip.getTextureClip(context, mipmapLevel, textureAccess, textureBufferWidth, textureHeight);
            }

            renderingInitialized = true;
        }
Пример #4
0
        private RendererTemplate compileRenderer(BasePrimitiveRenderer renderer, LongLongKey id, GeContext context)
        {
            if (log.InfoEnabled)
            {
                Console.WriteLine(string.Format("Compiling Renderer {0}", id));
            }

            Dictionary <string, object> variables = new Dictionary <string, object>();

            // All these variables have to be defined as static members in the class RendererTemplate.
            variables["hasMemInt"]                = Convert.ToBoolean(RuntimeContext.hasMemoryInt());
            variables["transform2D"]              = Convert.ToBoolean(renderer.transform2D);
            variables["clearMode"]                = Convert.ToBoolean(renderer.clearMode);
            variables["clearModeColor"]           = Convert.ToBoolean(context.clearModeColor);
            variables["clearModeStencil"]         = Convert.ToBoolean(context.clearModeStencil);
            variables["clearModeDepth"]           = Convert.ToBoolean(context.clearModeDepth);
            variables["needSourceDepthRead"]      = Convert.ToBoolean(renderer.needSourceDepthRead);
            variables["needDestinationDepthRead"] = Convert.ToBoolean(renderer.needDestinationDepthRead);
            variables["needDepthWrite"]           = Convert.ToBoolean(renderer.needDepthWrite);
            variables["needTextureUV"]            = Convert.ToBoolean(renderer.needTextureUV);
            variables["simpleTextureUV"]          = Convert.ToBoolean(renderer.simpleTextureUV);
            variables["swapTextureUV"]            = Convert.ToBoolean(renderer.swapTextureUV);
            variables["needScissoringX"]          = Convert.ToBoolean(renderer.needScissoringX);
            variables["needScissoringY"]          = Convert.ToBoolean(renderer.needScissoringY);
            variables["nearZ"] = new int?(renderer.nearZ);
            variables["farZ"]  = new int?(renderer.farZ);
            variables["colorTestFlagEnabled"]   = Convert.ToBoolean(context.colorTestFlag.Enabled);
            variables["colorTestFunc"]          = new int?(context.colorTestFunc);
            variables["alphaTestFlagEnabled"]   = Convert.ToBoolean(context.alphaTestFlag.Enabled);
            variables["alphaFunc"]              = new int?(context.alphaFunc);
            variables["alphaRef"]               = new int?(context.alphaRef);
            variables["alphaMask"]              = new int?(context.alphaMask);
            variables["stencilTestFlagEnabled"] = Convert.ToBoolean(context.stencilTestFlag.Enabled);
            variables["stencilFunc"]            = new int?(context.stencilFunc);
            variables["stencilOpFail"]          = new int?(context.stencilOpFail);
            variables["stencilOpZFail"]         = new int?(context.stencilOpZFail);
            variables["stencilOpZPass"]         = new int?(context.stencilOpZPass);
            variables["stencilRef"]             = new int?(context.stencilRef);
            variables["depthTestFlagEnabled"]   = Convert.ToBoolean(context.depthTestFlag.Enabled);
            variables["depthFunc"]              = new int?(context.depthFunc);
            variables["blendFlagEnabled"]       = Convert.ToBoolean(context.blendFlag.Enabled);
            variables["blendEquation"]          = new int?(context.blendEquation);
            variables["blendSrc"]               = new int?(context.blend_src);
            variables["blendDst"]               = new int?(context.blend_dst);
            variables["sfix"] = new int?(context.sfix);
            variables["dfix"] = new int?(context.dfix);
            variables["colorLogicOpFlagEnabled"] = Convert.ToBoolean(context.colorLogicOpFlag.Enabled);
            variables["logicOp"]                 = new int?(context.logicOp);
            variables["colorMask"]               = new int?(PixelColor.getColor(context.colorMask));
            variables["depthMask"]               = Convert.ToBoolean(context.depthMask);
            variables["textureFlagEnabled"]      = Convert.ToBoolean(context.textureFlag.Enabled);
            variables["useVertexTexture"]        = Convert.ToBoolean(renderer.useVertexTexture);
            variables["lightingFlagEnabled"]     = Convert.ToBoolean(context.lightingFlag.Enabled);
            variables["sameVertexColor"]         = Convert.ToBoolean(renderer.sameVertexColor);
            variables["setVertexPrimaryColor"]   = Convert.ToBoolean(renderer.setVertexPrimaryColor);
            variables["primaryColorSetGlobally"] = Convert.ToBoolean(renderer.primaryColorSetGlobally);
            variables["isTriangle"]              = Convert.ToBoolean(renderer.isTriangle);
            variables["matFlagAmbient"]          = Convert.ToBoolean((context.mat_flags & CMAT_FLAG_AMBIENT) != 0);
            variables["matFlagDiffuse"]          = Convert.ToBoolean((context.mat_flags & CMAT_FLAG_DIFFUSE) != 0);
            variables["matFlagSpecular"]         = Convert.ToBoolean((context.mat_flags & CMAT_FLAG_SPECULAR) != 0);
            variables["useVertexColor"]          = Convert.ToBoolean(context.useVertexColor);
            variables["textureColorDoubled"]     = Convert.ToBoolean(context.textureColorDoubled);
            variables["lightMode"]               = new int?(context.lightMode);
            variables["texMapMode"]              = new int?(context.tex_map_mode);
            variables["texProjMapMode"]          = new int?(context.tex_proj_map_mode);
            variables["texTranslateX"]           = new float?(context.tex_translate_x);
            variables["texTranslateY"]           = new float?(context.tex_translate_y);
            variables["texScaleX"]               = new float?(context.tex_scale_x);
            variables["texScaleY"]               = new float?(context.tex_scale_y);
            variables["texWrapS"]                = new int?(context.tex_wrap_s);
            variables["texWrapT"]                = new int?(context.tex_wrap_t);
            variables["textureFunc"]             = new int?(context.textureFunc);
            variables["textureAlphaUsed"]        = Convert.ToBoolean(context.textureAlphaUsed);
            variables["psm"]                  = new int?(context.psm);
            variables["texMagFilter"]         = new int?(context.tex_mag_filter);
            variables["needTextureWrapU"]     = Convert.ToBoolean(renderer.needTextureWrapU);
            variables["needTextureWrapV"]     = Convert.ToBoolean(renderer.needTextureWrapV);
            variables["needSourceDepthClamp"] = Convert.ToBoolean(renderer.needSourceDepthClamp);
            variables["isLogTraceEnabled"]    = Convert.ToBoolean(renderer.isLogTraceEnabled);
            variables["collectStatistics"]    = Convert.ToBoolean(DurationStatistics.collectStatistics);
            variables["ditherFlagEnabled"]    = Convert.ToBoolean(context.ditherFlag.Enabled);

            string           specializedClassName = NewCompiledRendererClassName;
            ClassSpecializer cs = new ClassSpecializer();
            Type             specializedClass = cs.specialize(specializedClassName, typeof(RendererTemplate), variables);
            RendererTemplate compiledRenderer = null;

            if (specializedClass != null)
            {
                try
                {
                    compiledRenderer = (RendererTemplate)System.Activator.CreateInstance(specializedClass);
                }
                catch (InstantiationException e)
                {
                    Console.WriteLine("Error while instanciating compiled renderer", e);
                }
                catch (IllegalAccessException e)
                {
                    Console.WriteLine("Error while instanciating compiled renderer", e);
                }
            }

            return(compiledRenderer);
        }
Пример #5
0
        public virtual RendererTemplate getCompiledRenderer(BasePrimitiveRenderer renderer, LongLongKey id, GeContext context)
        {
            RendererTemplate compiledRenderer = compiledRenderers[id];

            if (compiledRenderer == null)
            {
                compiledRenderer = compileRenderer(renderer, id, context);
                if (compiledRenderer != null)
                {
                    compiledRenderers[id] = compiledRenderer;
                }
            }

            return(compiledRenderer);
        }
Пример #6
0
        private void setVertexTextures(GeContext context, float[] c1, float[] c2, float[] c3)
        {
            textureWidth  = context.texture_width[mipmapLevel];
            textureHeight = context.texture_height[mipmapLevel];

            // The rendering will be performed into the following ranges:
            // 3D:
            //   - x: [pxMin..pxMax] (min and max included)
            //   - y: [pxMin..pxMax] (min and max included)
            // 2D:
            //   - x: [pxMin..pxMax-1] (min included but max excluded)
            //   - y: [pxMin..pxMax-1] (min included but max excluded)
            if (transform2D)
            {
                prim.pxMax--;
                prim.pyMax--;
            }
            else
            {
                // Restrict the drawn area to the scissor area.
                // We can just update the min/max values, the TextureMapping filter
                // will take are of the correct texture mapping.
                // We do no longer need a scissoring filter.
                if (needScissoringX)
                {
                    prim.pxMin      = max(prim.pxMin, scissorX1);
                    prim.pxMax      = min(prim.pxMax, scissorX2);
                    needScissoringX = false;
                }
                if (needScissoringY)
                {
                    prim.pyMin      = max(prim.pyMin, scissorY1);
                    prim.pyMax      = min(prim.pyMax, scissorY2);
                    needScissoringY = false;
                }
            }
            prim.destinationWidth  = prim.pxMax - prim.pxMin + 1;
            prim.destinationHeight = prim.pyMax - prim.pyMin + 1;

            if (isUsingTexture(context))
            {
                simpleTextureUV = !isTriangle;

                if (!simpleTextureUV && isTriangle && transform2D)
                {
                    // Check if the 2D triangle can be rendered using a simple texture UV mapping:
                    // this is only possible when the triangle has a square angle.
                    //
                    // 1---2     1---2     1             1
                    // |  /       \  |     | \         / |
                    // | /         \ |     |  \       /  |
                    // 3             3     3---2     3---2
                    //
                    // 1---3     1---3     1             1
                    // |  /       \  |     | \         / |
                    // | /         \ |     |  \       /  |
                    // 2             2     2---3     2---3
                    //
                    if (prim.p1x == prim.p2x && prim.t1u == prim.t2u)
                    {
                        if (prim.p1y == prim.p3y && prim.t1v == prim.t3v)
                        {
                            simpleTextureUV = true;
                        }
                        else if (prim.p2y == prim.p3y && prim.t2v == prim.t3v)
                        {
                            simpleTextureUV = true;
                        }
                    }
                    else if (prim.p1x == prim.p3x && prim.t1u == prim.t3u)
                    {
                        if (prim.p1y == prim.p2y && prim.t1v == prim.t2v)
                        {
                            simpleTextureUV = true;
                        }
                        else if (prim.p2y == prim.p3y && prim.t2v == prim.t3v)
                        {
                            simpleTextureUV = true;
                        }
                    }
                    else if (prim.p2x == prim.p3x && prim.t2u == prim.t3u)
                    {
                        if (prim.p1y == prim.p2y && prim.t1v == prim.t2v)
                        {
                            simpleTextureUV = true;
                        }
                        else if (prim.p1y == prim.p1y && prim.t2v == prim.t3v)
                        {
                            simpleTextureUV = true;
                        }
                    }
                }

                if (simpleTextureUV)
                {
                    if (transform2D)
                    {
                        bool flipX = false;
                        bool flipY = false;
                        if (isTriangle)
                        {
                            // Compute texture flips for a triangle
                            if (prim.t1u != prim.t2u)
                            {
                                flipX = (prim.t1u > prim.t2u) ^ (prim.p1x > prim.p2x);
                            }
                            if (prim.t1v != prim.t2v)
                            {
                                flipY = (prim.t1v > prim.t2v) ^ (prim.p1y > prim.p2y);
                            }
                            if (!flipX && prim.t2u != prim.t3u)
                            {
                                flipX = (prim.t2u > prim.t3u) ^ (prim.p2x > prim.p3x);
                            }
                            if (!flipY && prim.t2v != prim.t3v)
                            {
                                flipY = (prim.t2v > prim.t3v) ^ (prim.p2y > prim.p3y);
                            }
                        }
                        else
                        {
                            // Compute texture flips for a sprite
                            flipX = (prim.t1u > prim.t2u) ^ (prim.p1x > prim.p2x);
                            flipY = (prim.t1v > prim.t2v) ^ (prim.p1y > prim.p2y);
                            if (flipX && flipY)
                            {
                                swapTextureUV = true;
                                flipX         = false;
                                flipY         = false;
                            }
                        }
                        if (isLogTraceEnabled)
                        {
//JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET:
//ORIGINAL LINE: log.trace(String.format("2D texture flipX=%b, flipY=%b, swapUV=%b, point (%d,%d)-(%d,%d), texture (%d,%d)-(%d,%d)", flipX, flipY, swapTextureUV, prim.pxMin, prim.pyMin, prim.pxMax, prim.pyMax, prim.tuMin, prim.tvMin, prim.tuMax, prim.tvMax));
                            log.trace(string.Format("2D texture flipX=%b, flipY=%b, swapUV=%b, point (%d,%d)-(%d,%d), texture (%d,%d)-(%d,%d)", flipX, flipY, swapTextureUV, prim.pxMin, prim.pyMin, prim.pxMax, prim.pyMax, prim.tuMin, prim.tvMin, prim.tuMax, prim.tvMax));
                        }
                        prim.uStart = flipX ? prim.tuMax : prim.tuMin;
                        float uEnd = flipX ? prim.tuMin : prim.tuMax;
                        prim.vStart = flipY ? prim.tvMax : prim.tvMin;
                        float vEnd = flipY ? prim.tvMin : prim.tvMax;
                        prim.uStep = (uEnd - prim.uStart) / (swapTextureUV ? prim.destinationHeight : prim.destinationWidth);
                        prim.vStep = (vEnd - prim.vStart) / (swapTextureUV ? prim.destinationWidth : prim.destinationHeight);
                    }
                    else
                    {
                        // 3D sprite
                        prim.uStart = prim.t1u;
                        float uEnd = prim.t2u;
                        prim.vStart = prim.t1v;
                        float vEnd = prim.t2v;
                        if (prim.p1x == prim.p2x)
                        {
                            prim.uStep = 1f;
                        }
                        else
                        {
                            prim.uStep = (uEnd - prim.uStart) / System.Math.Abs(prim.p2x - prim.p1x);
                        }
                        if (prim.p1y == prim.p2y)
                        {
                            prim.vStep = 1f;
                        }
                        else
                        {
                            prim.vStep = (vEnd - prim.vStart) / System.Math.Abs(prim.p2y - prim.p1y);
                        }
                        if (isLogTraceEnabled)
                        {
                            log.trace(string.Format("3D sprite uStart={0:F}, uStep={1:F}, vStart={2:F}, vStep={3:F}, texTranslateX={4:F}, texTranslateY={5:F}, texScaleX={6:F}, texScaleY={7:F}, point ({8:D},{9:D})-({10:D},{11:D}), texture ({12:D},{13:D})-({14:D},{15:D})", prim.uStart, prim.uStep, prim.vStart, prim.vStep, texTranslateX, texTranslateY, texScaleX, texScaleY, prim.pxMin, prim.pyMin, prim.pxMax, prim.pyMax, prim.tuMin, prim.tvMin, prim.tuMax, prim.tvMax));
                        }
                    }

                    // Perform scissoring and update uStart/uStep and vStart/vStep
                    if (needScissoringX)
                    {
                        int deltaX = scissorX1 - prim.pxMin;
                        if (deltaX > 0)
                        {
                            prim.uStart += prim.uStep * deltaX;
                            prim.pxMin  += deltaX;
                            if (transform2D)
                            {
                                prim.tuMin += Round(prim.uStep * deltaX);
                            }
                        }
                        deltaX = prim.pxMax - scissorX2;
                        if (deltaX > 0)
                        {
                            prim.pxMax -= deltaX;
                            if (transform2D)
                            {
                                prim.tuMax -= Round(prim.uStep * deltaX);
                            }
                        }
                        prim.destinationWidth = prim.pxMax - prim.pxMin + 1;
                        needScissoringX       = false;
                    }
                    if (needScissoringY)
                    {
                        int deltaY = scissorY1 - prim.pyMin;
                        if (deltaY > 0)
                        {
                            prim.vStart += prim.vStep * deltaY;
                            prim.pyMin  += deltaY;
                            if (transform2D)
                            {
                                prim.tvMin += Round(prim.vStep * deltaY);
                            }
                        }
                        deltaY = prim.pyMax - scissorY2;
                        if (deltaY > 0)
                        {
                            prim.pyMax -= deltaY;
                            if (transform2D)
                            {
                                prim.tvMax -= Round(prim.vStep * deltaY);
                            }
                        }
                        prim.destinationHeight = prim.pyMax - prim.pyMin + 1;
                        needScissoringY        = false;
                    }
                }
            }

            if (setVertexPrimaryColor)
            {
                if (c3 != null)
                {
                    pixel.c1a = getColor(c1[3]);
                    pixel.c1b = getColor(c1[2]);
                    pixel.c1g = getColor(c1[1]);
                    pixel.c1r = getColor(c1[0]);
                    pixel.c2a = getColor(c2[3]);
                    pixel.c2b = getColor(c2[2]);
                    pixel.c2g = getColor(c2[1]);
                    pixel.c2r = getColor(c2[0]);
                    pixel.c3a = getColor(c3[3]);
                    pixel.c3b = getColor(c3[2]);
                    pixel.c3g = getColor(c3[1]);
                    pixel.c3r = getColor(c3[0]);
                    pixel.c3  = getColor(c3);
                }
                if (isTriangle)
                {
                    if (context.shadeModel == GeCommands.SHADE_TYPE_FLAT)
                    {
                        // Flat shade model: always use the color of the 3rd triangle vertex
                        sameVertexColor = true;
                    }
                    else
                    {
                        sameVertexColor = Utilities.sameColor(c1, c2, c3);
                    }
                    // For triangles, take the weighted color from the 3 vertices.
                }
                else
                {
                    // For sprites, take only the color from the 2nd vertex
                    primaryColor = getColor(c2);
                    if (context.textureColorDoubled)
                    {
                        primaryColor = doubleColor(primaryColor);
                    }
                }
            }

            // Try to avoid to compute expensive values
            needDepthWrite           = getNeedDepthWrite(context);
            needSourceDepthRead      = needDepthWrite || getNeedSourceDepthRead(context);
            needDestinationDepthRead = getNeedDestinationDepthRead(context, needDepthWrite);
            if (zbw <= 0)
            {
                needDepthWrite           = false;
                needSourceDepthRead      = false;
                needDestinationDepthRead = false;
            }
            needTextureUV = getNeedTextureUV(context);
            if (transform2D)
            {
                needTextureWrapU = prim.tuMin < 0 || prim.tuMax >= context.texture_width[mipmapLevel];
                needTextureWrapV = prim.tvMin < 0 || prim.tvMax >= context.texture_height[mipmapLevel];
            }
            else
            {
                if (context.tex_map_mode != GeCommands.TMAP_TEXTURE_MAP_MODE_TEXTURE_COORDIATES_UV)
                {
                    needTextureWrapU = true;
                    needTextureWrapV = true;
                }
                else if (isTriangle && (prim.p1w <= 0f || prim.p2w <= 0f || prim.p3w <= 0f))
                {
                    // Need texture wrapping if one triangle point is behind the eye:
                    // the texture coordinates might exceed the calculated range due to the perspective correction.
                    needTextureWrapU = true;
                    needTextureWrapV = true;
                }
                else
                {
                    float tuMin, tuMax;
                    float tvMin, tvMax;
                    if (isTriangle)
                    {
                        tuMin = Utilities.min(prim.t1u, Utilities.min(prim.t2u, prim.t3u));
                        tuMax = Utilities.max(prim.t1u, Utilities.max(prim.t2u, prim.t3u));
                        tvMin = Utilities.min(prim.t1v, Utilities.min(prim.t2v, prim.t3v));
                        tvMax = Utilities.max(prim.t1v, Utilities.max(prim.t2v, prim.t3v));
                    }
                    else
                    {
                        tuMin = Utilities.min(prim.t1u, prim.t2u);
                        tuMax = Utilities.max(prim.t1u, prim.t2u);
                        tvMin = Utilities.min(prim.t1v, prim.t2v);
                        tvMax = Utilities.max(prim.t1v, prim.t2v);
                    }
                    tuMin            = tuMin * texScaleX + texTranslateX;
                    tuMax            = tuMax * texScaleX + texTranslateX;
                    tvMin            = tvMin * texScaleY + texTranslateY;
                    tvMax            = tvMax * texScaleY + texTranslateY;
                    needTextureWrapU = tuMin < 0f || tuMin >= 0.99999f || tuMax < 0f || tuMax >= 0.99999f;
                    needTextureWrapV = tvMin < 0f || tvMin >= 0.99999f || tvMax < 0f || tvMax >= 0.99999f;
                }
            }
            needSourceDepthClamp = false;
            if (needDepthWrite && needSourceDepthRead && isTriangle)
            {
                if (prim.p1z < 0f || prim.p2z < 0f || prim.p3z < 0f)
                {
                    needSourceDepthClamp = true;
                }
                else if (prim.p1z > 65535f || prim.p2z > 65535f || prim.p3z > 65535f)
                {
                    needSourceDepthClamp = true;
                }
            }

            prepareWriters();

            LongLongKey rendererKey = RendererKey;

            if (compiledRenderer == null || !rendererKey.Equals(compiledRendererKey))
            {
                compiledRendererKey = rendererKey;
                compiledRenderer    = FilterCompiler.Instance.getCompiledRenderer(this, rendererKey, context);
                if (isLogTraceEnabled)
                {
//JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method:
                    log.trace(string.Format("Rendering using compiled renderer {0}", compiledRenderer.GetType().FullName));
                }
            }

            if (c3 != null)
            {
                prim.preComputeTriangleWeights();
            }
        }