Beispiel #1
0
        private void deleteShaders()
        {
            if (mProgramId != 0)
            {
                // this causes an exception EntryPointNotFound ..
                // GL.DeleteProgram (1, ref mProgramId  );
                mProgramId = 0;
            }

            if (mVertexShaderId != 0)
            {
                GL.DeleteShader(mVertexShaderId);
                GLUtils.CheckGLError();
                mVertexShaderId = 0;
            }

            if (mFragmentShaderId != 0)
            {
                GL.DeleteShader(mFragmentShaderId);
                GLUtils.CheckGLError();
                mFragmentShaderId = 0;
            }

            if (mMemUsage != 0)
            {
                mContext.statsDecrement(Context3D.Stats.Count_Program);
                mContext.statsSubtract(Context3D.Stats.Mem_Program, mMemUsage);
                mMemUsage = 0;
            }
        }
Beispiel #2
0
 internal void SetPositionScale(float[] positionScale)
 {
     // update position scale
     if (mPositionScale != null)
     {
         GL.Uniform4(mPositionScale.Location, 1, positionScale);
         GLUtils.CheckGLError();
     }
 }
Beispiel #3
0
        public unsafe void uploadFromPointer(void *data, int dataLength, int startOffset, int count)
        {
            // swap to next buffer
            mBufferIndex++;
            if (mBufferIndex >= mIds.Length)
            {
                mBufferIndex = 0;
            }

            // get size of each index
            int elementSize = sizeof(ushort);

            int byteCount = count * elementSize;

            // bounds check
            if (byteCount > dataLength)
            {
                throw new ArgumentOutOfRangeException("data buffer is not big enough for upload");
            }

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, mIds[mBufferIndex]);
            GLUtils.CheckGLError();

            if (startOffset == 0)
            {
                GL.BufferData(BufferTarget.ElementArrayBuffer,
                              new IntPtr(byteCount),
                              new IntPtr(data),
                              mUsage);
                GLUtils.CheckGLError();

                if (byteCount != mMemoryUsage)
                {
                    // update stats for memory usage
                    mContext.statsAdd(Context3D.Stats.Mem_IndexBuffer, byteCount - mMemoryUsage);
                    mMemoryUsage = byteCount;
                }
            }
            else
            {
                // update range of index buffer
                GL.BufferSubData(BufferTarget.ElementArrayBuffer,
                                 new IntPtr(startOffset * elementSize),
                                 new IntPtr(byteCount),
                                 new IntPtr(data));
                GLUtils.CheckGLError();
            }
        }
Beispiel #4
0
        public void uploadFromBitmapData(BitmapData source, uint miplevel = 0, bool generateMipmap = false)
        {
            int memUsage = (mWidth * mHeight) * 4;

            sMemoryUsedForTextures += memUsage;
            Console.WriteLine("Texture.uploadFromBitmapData() - " + mWidth + "x" + mHeight + " - Mem: " + (memUsage / 1024) + " KB - Total Mem: " + (sMemoryUsedForTextures / 1024) + " KB");

            // Bind the texture
            GL.BindTexture(textureTarget, textureId);
            GLUtils.CheckGLError();

                        #if PLATFORM_MONOMAC
            if (generateMipmap)
            {
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, 1);
            }
                        #endif

                        #if PLATFORM_MONOMAC || PLATFORM_MONOTOUCH
            GL.TexImage2D(textureTarget, (int)miplevel, PixelInternalFormat.Rgba, mWidth, mHeight, 0, PixelFormat.Rgba, PixelType.UnsignedByte, source.getRawData());
            mAllocated = true;
                        #elif PLATFORM_MONODROID
            GL.TexImage2D <uint>(textureTarget, (int)miplevel, (int)PixelInternalFormat.Rgba, mWidth, mHeight, 0, PixelFormat.Rgba, PixelType.UnsignedByte, source.getRawData());
            GLUtils.CheckGLError();
            mAllocated = true;
                        #endif

                        #if PLATFORM_MONOTOUCH || PLATFORM_MONODROID
            if (generateMipmap)
            {
                GL.GenerateMipmap(textureTarget);
                GLUtils.CheckGLError();
            }
                        #endif

            // unbind texture and pixel buffer
            GL.BindTexture(textureTarget, 0);
            GLUtils.CheckGLError();

            // Uhh... no!  BEN
//			source.dispose();

            // store memory usaged by texture
            trackMemoryUsage(memUsage);
        }
Beispiel #5
0
        internal void Use()
        {
            // use program
            GL.UseProgram(mProgramId);
            GLUtils.CheckGLError();

            // update texture units for all sampler uniforms
            foreach (var sampler in mSamplerUniforms)
            {
                if (sampler.RegCount == 1)
                {
                    // single sampler
                    GL.Uniform1(sampler.Location, sampler.RegIndex);
                    GLUtils.CheckGLError();
                }
                else
                {
                    // sampler array?
                    for (int i = 0; i < sampler.RegCount; i++)
                    {
                        GL.Uniform1(sampler.Location + i, sampler.RegIndex + i);
                        GLUtils.CheckGLError();
                    }
                }
            }

            foreach (var sampler in mAlphaSamplerUniforms)
            {
                if (sampler.RegCount == 1)
                {
                    // single sampler
                    GL.Uniform1(sampler.Location, sampler.RegIndex);
                    GLUtils.CheckGLError();
                }
                else
                {
                    // sampler array?
                    for (int i = 0; i < sampler.RegCount; i++)
                    {
                        GL.Uniform1(sampler.Location + i, sampler.RegIndex + i);
                        GLUtils.CheckGLError();
                    }
                }
            }
        }
Beispiel #6
0
        //
        // Methods
        //

#if OPENGL
        internal IndexBuffer3D(Context3D context3D, int numIndices, int multiBufferCount, bool isDynamic)
        {
            if (multiBufferCount < 1)
            {
                throw new ArgumentOutOfRangeException("multiBufferCount");
            }

            mContext     = context3D;
            mNumIndices  = numIndices;
            mIds         = new uint[multiBufferCount];
            mElementType = DrawElementsType.UnsignedShort;
            GL.GenBuffers(multiBufferCount, mIds);
            GLUtils.CheckGLError();

            mUsage = isDynamic ? BufferUsage.DynamicDraw : BufferUsage.StaticDraw;

            // update stats
            mContext.statsIncrement(Context3D.Stats.Count_IndexBuffer);
        }
Beispiel #7
0
        public unsafe void uploadFromByteArray(ByteArray data, uint byteArrayOffset, uint miplevel = 0)
        {
            int memUsage = (mWidth * mHeight) * 4;

            sMemoryUsedForTextures += memUsage;
            Console.WriteLine("Texture.uploadFromByteArray() - " + mWidth + "x" + mHeight + " - Mem: " + (memUsage / 1024) + " KB - Total Mem: " + (sMemoryUsedForTextures / 1024) + " KB");

            // Bind the texture
            GL.BindTexture(textureTarget, textureId);
            GLUtils.CheckGLError();

                        #if PLATFORM_MONOMAC || PLATFORM_MONOTOUCH
            // pin pointer to byte array data
            fixed(byte *bytePtr = data.getRawArray())
            {
                IntPtr ptr = (IntPtr)bytePtr;

                GL.TexImage2D(textureTarget, (int)miplevel, PixelInternalFormat.Rgba, mWidth, mHeight, 0, PixelFormat.Rgba, PixelType.UnsignedByte, ptr);
            }

            mAllocated = true;
                        #elif PLATFORM_MONODROID
            fixed(byte *ptr = data.getRawArray())
            {
                var address = new IntPtr(ptr + data.position);

                GL.TexImage2D(textureTarget, (int)miplevel, (int)PixelInternalFormat.Rgba, (int)mWidth, (int)mHeight, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)address);
            }

            GLUtils.CheckGLError();
            mAllocated = true;
                        #endif

            // unbind texture and pixel buffer
            GL.BindTexture(textureTarget, 0);
            GLUtils.CheckGLError();

            // store memory usaged by texture
            trackMemoryUsage(memUsage);
        }
Beispiel #8
0
        private unsafe void uploadATFTextureFromByteArray(ByteArray data, uint byteArrayOffset)
        {
            data.position = byteArrayOffset;

            // read atf signature
            string signature = data.readUTFBytes(3);

            if (signature != "ATF")
            {
                throw new InvalidDataException("ATF signature not found");
            }

            // read atf length
            uint length = readUInt24(data);

            if ((byteArrayOffset + length) > data.length)
            {
                throw new InvalidDataException("ATF length exceeds byte array length");
            }

            // get format
            uint    tdata = data.readUnsignedByte( );
            AtfType type  = (AtfType)(tdata >> 7);

            if (type != AtfType.NORMAL)
            {
                throw new NotImplementedException("ATF Cube maps are not supported");
            }

//			Removing ATF format limitation to allow for multiple format support.
//			AtfFormat format = (AtfFormat)(tdata & 0x7f);
//			if (format != AtfFormat.Block) {
//				throw new NotImplementedException("Only ATF block compressed textures are supported");
//			}

            // get dimensions
            int width  = (1 << (int)data.readUnsignedByte());
            int height = (1 << (int)data.readUnsignedByte());

            if (width != mWidth || height != mHeight)
            {
                throw new InvalidDataException("ATF Width and height dont match");
            }

            // get mipmap count
            int mipCount = (int)data.readUnsignedByte();

            // read all mipmap levels
            for (int level = 0; level < mipCount; level++)
            {
                // read all gpu formats
                for (int gpuFormat = 0; gpuFormat < 3; gpuFormat++)
                {
                    // read block length
                    uint blockLength = readUInt24(data);
                    if ((data.position + blockLength) > data.length)
                    {
                        throw new System.IO.InvalidDataException("Block length exceeds ATF file length");
                    }

                    if (blockLength > 0)
                    {
                        // handle PVRTC on iOS
                        if (gpuFormat == 1)
                        {
                                                        #if PLATFORM_MONOTOUCH
                            OpenTK.Graphics.ES20.PixelInternalFormat pixelFormat = (OpenTK.Graphics.ES20.PixelInternalFormat) 0x8C02;
                            fixed(byte *ptr = data.getRawArray())
                            {
                                // upload from data position
                                var address = new IntPtr(ptr + data.position);

                                GL.CompressedTexImage2D(textureTarget, level, pixelFormat, width, height, 0, (int)blockLength, address);
                                mAllocated = true;
                            }

                            trackCompressedMemoryUsage((int)blockLength);
                                                        #endif
                        }
                        else if (gpuFormat == 2)
                        {
                                                        #if PLATFORM_MONODROID
                            int textureLength = width * height / 2;
                            fixed(byte *ptr = data.getRawArray())
                            {
                                var address = new IntPtr(ptr + data.position);

                                GL.CompressedTexImage2D(textureTarget, level, All.Etc1Rgb8Oes, width, height, 0, (int)textureLength, address);

                                GLUtils.CheckGLError();

                                mAllocated = true;
                                if (textureLength < blockLength)
                                {
                                    mAlphaTexture = new Texture(mContext, width, height, mFormat, mOptimizeForRenderToTexture, mStreamingLevels);
                                    var alphaAddress = new IntPtr(ptr + data.position + textureLength);

                                    GL.BindTexture(mAlphaTexture.textureTarget, mAlphaTexture.textureId);
                                    GLUtils.CheckGLError();
                                    GL.CompressedTexImage2D(mAlphaTexture.textureTarget, level, All.Etc1Rgb8Oes, width, height, 0, textureLength, alphaAddress);
                                    GLUtils.CheckGLError();
                                    GL.BindTexture(mAlphaTexture.textureTarget, 0);
                                    GLUtils.CheckGLError();
                                    mAllocated = true;
                                }
                                else
                                {
                                    mAlphaTexture = new Texture(mContext, 1, 1, mFormat, mOptimizeForRenderToTexture, mStreamingLevels);
                                    var clearData = new BitmapData(width, height, true, 0xFFFFFFFF);

                                    GL.BindTexture(mAlphaTexture.textureTarget, mAlphaTexture.textureId);
                                    GLUtils.CheckGLError();
                                    GL.TexImage2D(mAlphaTexture.textureTarget, level, (int)PixelInternalFormat.Rgba, 1, 1, 0, PixelFormat.Rgba, PixelType.UnsignedByte, clearData.getRawData());
                                    GLUtils.CheckGLError();
                                    GL.BindTexture(mAlphaTexture.textureTarget, 0);
                                    GLUtils.CheckGLError();

                                    mAllocated = true;
                                    clearData.dispose();
                                }
                            }

                            trackCompressedMemoryUsage((int)blockLength);
                                                        #endif
                        }

                        // TODO handle other formats/platforms
                    }

                    // next block data
                    data.position += blockLength;
                }
            }
        }
Beispiel #9
0
        public void uploadCompressedTextureFromByteArray(ByteArray data, uint byteArrayOffset, bool async = false)
        {
#if PLATFORM_MONOMAC
            System.Console.WriteLine("NotImplementedWarning: Texture.uploadCompressedTextureFromByteArray()");

            if (!mDidUpload)
            {
                var clearData = new BitmapData(32, 32, true, sColors[sColor % sColors.Length]);
                sColor++;
                uploadFromBitmapData(clearData);
                clearData.dispose();
                mDidUpload = true;
            }
#endif

            // see if this is an ATF container
            data.position = byteArrayOffset;
            string signature = data.readUTFBytes(3);
            data.position = byteArrayOffset;
            if (signature == "ATF")
            {
                // Bind the texture
                GL.BindTexture(textureTarget, textureId);
                GLUtils.CheckGLError();

                uploadATFTextureFromByteArray(data, byteArrayOffset);

                GL.BindTexture(textureTarget, 0);
                GLUtils.CheckGLError();
            }
            else
            {
#if PLATFORM_MONOTOUCH || PLATFORM_MONODROID
                int memUsage = (mWidth * mHeight) / 2;
                sMemoryUsedForTextures += memUsage;
                Console.WriteLine("Texture.uploadCompressedTextureFromByteArray() - " + mWidth + "x" + mHeight + " - Mem: " + (memUsage / 1024) + " KB - Total Mem: " + (sMemoryUsedForTextures / 1024) + " KB");

                // Bind the texture
                GL.BindTexture(textureTarget, textureId);
                GLUtils.CheckGLError();

                if (byteArrayOffset != 0)
                {
                    throw new NotSupportedException();
                }

                #if PLATFORM_MONOTOUCH
                int dataLength = (int)(data.length - byteArrayOffset) - 4;                      // We remove the 4 bytes footer

                // TODO: Fix hardcoded value here
                OpenTK.Graphics.ES20.PixelInternalFormat pixelFormat = (OpenTK.Graphics.ES20.PixelInternalFormat) 0x8C02;

                GL.CompressedTexImage2D(textureTarget, 0, pixelFormat, mWidth, mHeight, 0, dataLength, data.getRawArray());
                mAllocated = true;
                #elif PLATFORM_MONODROID
                data.position = 16;         // skip the header
                int dataLength = ((int)data.length) - 16;

                GL.CompressedTexImage2D <byte>(textureTarget, 0, All.Etc1Rgb8Oes, mWidth, mHeight, 0, dataLength, data.getRawArray());
                mAllocated = true;
                #endif

                trackCompressedMemoryUsage(dataLength);

                // unbind texture and pixel buffer
                GL.BindTexture(textureTarget, 0);
                GLUtils.CheckGLError();
#endif
            }

            if (async)
            {
                // load with a delay
                var timer = new flash.utils.Timer(1, 1);
                timer.addEventListener(TimerEvent.TIMER, (System.Action <Event>) this.OnTextureReady);
                timer.start();
            }
        }
Beispiel #10
0
        private void buildUniformList()
        {
            // clear internal lists
            mUniforms.Clear();
            mVertexUniformLookup   = new Uniform[MaxUniforms];
            mFragmentUniformLookup = new Uniform[MaxUniforms];
            mSamplerUniforms.Clear();
            mAlphaSamplerUniforms.Clear();

            mSamplerUsageMask = 0;

            int numActive = 0;

            GL.GetProgram(mProgramId, ProgramParameter.ActiveUniforms, out numActive);
            GLUtils.CheckGLError();

            for (int i = 0; i < numActive; i++)
            {
                // create new uniform
                int size = 0;
                ActiveUniformType uniformType;
                var name = GL.GetActiveUniform(mProgramId, i, out size, out uniformType);
                GLUtils.CheckGLError();

                var uniform = new Uniform();
                uniform.Name = name.ToString();
                uniform.Size = size;
                uniform.Type = uniformType;

#if PLATFORM_MONOTOUCH || PLATFORM_MONOMAC
                uniform.Location = GL.GetUniformLocation(mProgramId, uniform.Name);
                GLUtils.CheckGLError();
#elif PLATFORM_MONODROID
                uniform.Location = GL.GetUniformLocation(mProgramId, new StringBuilder(uniform.Name, 0, uniform.Name.Length, uniform.Name.Length));
                GLUtils.CheckGLError();
#endif
                // remove array [x] from names
                int indexBracket = uniform.Name.IndexOf('[');
                if (indexBracket >= 0)
                {
                    uniform.Name = uniform.Name.Substring(0, indexBracket);
                }

                // determine register count for uniform
                switch (uniform.Type)
                {
                case ActiveUniformType.FloatMat2: uniform.RegCount = 2; break;

                case ActiveUniformType.FloatMat3: uniform.RegCount = 3; break;

                case ActiveUniformType.FloatMat4: uniform.RegCount = 4; break;

                default:
                    uniform.RegCount = 1;                     // 1 by default
                    break;
                }

                // multiple regcount by size
                uniform.RegCount *= uniform.Size;

                // add uniform to program list
                mUniforms.Add(uniform);

                if (uniform.Name == "vcPositionScale")
                {
                    mPositionScale = uniform;
                }
                else if (uniform.Name.StartsWith("vc"))
                {
                    // vertex uniform
                    uniform.RegIndex = int.Parse(uniform.Name.Substring(2));
                    // store in vertex lookup table
                    for (int reg = 0; reg < uniform.RegCount; reg++)
                    {
                        mVertexUniformLookup[uniform.RegIndex + reg] = uniform;
                    }
                }
                else if (uniform.Name.StartsWith("fc"))
                {
                    // fragment uniform
                    uniform.RegIndex = int.Parse(uniform.Name.Substring(2));
                    // store in fragment lookup table
                    for (int reg = 0; reg < uniform.RegCount; reg++)
                    {
                        mFragmentUniformLookup[uniform.RegIndex + reg] = uniform;
                    }
                }
                else if (uniform.Name.StartsWith("sampler") && !uniform.Name.EndsWith("_alpha"))
                {
                    // sampler uniform
                    uniform.RegIndex = int.Parse(uniform.Name.Substring(7));
                    // add to list of sampler uniforms
                    mSamplerUniforms.Add(uniform);

                    // set sampler usage mask for this sampler uniform
                    for (int reg = 0; reg < uniform.RegCount; reg++)
                    {
                        mSamplerUsageMask |= (1 << (uniform.RegIndex + reg));
                    }
                }
                else if (uniform.Name.StartsWith("sampler") && uniform.Name.EndsWith("_alpha"))
                {
                    // sampler uniform
                    int len = uniform.Name.IndexOf("_") - 7;
                    uniform.RegIndex = int.Parse(uniform.Name.Substring(7, len)) + 4;
                    // add to list of sampler uniforms
                    mAlphaSamplerUniforms.Add(uniform);
                }

                if (Verbose)
                {
                    Console.WriteLine("{0} name:{1} type:{2} size:{3} location:{4}", i, uniform.Name, uniform.Type, uniform.Size, uniform.Location);
                }
            }
        }
Beispiel #11
0
        public void uploadFromGLSL(string vertexShaderSource, string fragmentShaderSource)
        {
            // delete existing shaders
            deleteShaders();

            if (Verbose)
            {
                Console.WriteLine(vertexShaderSource);
                Console.WriteLine(fragmentShaderSource);
            }

            mVertexSource   = vertexShaderSource;
            mFragmentSource = fragmentShaderSource;

            // compiler vertex shader
            mVertexShaderId = GL.CreateShader(ShaderType.VertexShader);
            GL.ShaderSource(mVertexShaderId, vertexShaderSource);
            GLUtils.CheckGLError();

            GL.CompileShader(mVertexShaderId);
            GLUtils.CheckGLError();

            int shaderCompiled = 0;

            GL.GetShader(mVertexShaderId, ShaderParameter.CompileStatus, out shaderCompiled);
            GLUtils.CheckGLError();

            if (All.True != (All)shaderCompiled)
            {
                var vertexInfoLog = GL.GetShaderInfoLog(mVertexShaderId);
                if (!string.IsNullOrEmpty(vertexInfoLog))
                {
                    Console.Write("vertex: {0}", vertexInfoLog);
                }

                throw new Exception("Error compiling vertex shader: " + vertexInfoLog);
            }

            // compile fragment shader
            mFragmentShaderId = GL.CreateShader(ShaderType.FragmentShader);
            GL.ShaderSource(mFragmentShaderId, fragmentShaderSource);
            GLUtils.CheckGLError();

            GL.CompileShader(mFragmentShaderId);
            GLUtils.CheckGLError();

            int fragmentCompiled = 0;

            GL.GetShader(mFragmentShaderId, ShaderParameter.CompileStatus, out fragmentCompiled);

            if (All.True != (All)fragmentCompiled)
            {
                var fragmentInfoLog = GL.GetShaderInfoLog(mFragmentShaderId);
                if (!string.IsNullOrEmpty(fragmentInfoLog))
                {
                    Console.Write("fragment: {0}", fragmentInfoLog);
                }

                throw new Exception("Error compiling fragment shader: " + fragmentInfoLog);
            }

            // create program
            mProgramId = GL.CreateProgram();
            GL.AttachShader(mProgramId, mVertexShaderId);
            GLUtils.CheckGLError();

            GL.AttachShader(mProgramId, mFragmentShaderId);
            GLUtils.CheckGLError();

            // bind all attribute locations
            for (int i = 0; i < Context3D.MaxAttributes; i++)
            {
                var name = "va" + i;
                if (vertexShaderSource.Contains(" " + name))
                {
                    GL.BindAttribLocation(mProgramId, i, name);
                }
            }

            // Link the program
            GL.LinkProgram(mProgramId);

            var infoLog = GL.GetProgramInfoLog(mProgramId);

            if (!string.IsNullOrEmpty(infoLog))
            {
                Console.Write("program: {0}", infoLog);
            }

            // build uniform list
            buildUniformList();

            // update stats for this program
            mMemUsage = 1;             // TODO, figure out a way to get this
            mContext.statsIncrement(Context3D.Stats.Count_Program);
            mContext.statsAdd(Context3D.Stats.Mem_Program, mMemUsage);
        }