Skip to content

Tutorial: Drawing a texture

Adam Gorski edited this page Jul 8, 2021 · 1 revision

This short tutorial will help us draw a cube with a texture to the screen:

To begin, create a new windows form application and add the following variables to the top:

renderX GL;
GLBuffer vertexBuffer;
Shader cubeShader;

Vector3 cameraPosition, cameraRotation;

Next lets declare both our shaders:

unsafe void CubeVS(float* OUT, float* IN, int Index){
        OUT[0] = IN[0] * 50;
        OUT[1] = IN[1] * 50;
        OUT[2] = IN[2] * 50;
}

unsafe void CubeFS(byte* BGR, float* Attributes, int Index){
        float u = Attributes[0] * 255f;
        float v = Attributes[1] * 255f;
        BGR[0] = (byte)u;
        BGR[1] = (byte)v;
}

After that lets create our renderFrame method:

void timer_Tick(object sender, EventArgs e)
{
        GL.Clear(0, 0, 0);
        GL.ClearDepth();

        GL.SelectBuffer(vertexBuffer);
        GL.SelectShader(cubeShader);

        GL.Draw();
        GL.Blit();
}

Note: I recommend you use the RenderThread included, however this short demo will do fine with a 15.6ms limited timer

Lastly, lets add the Form1_Load event and add the following code:

//Set the form size to 800x600
this.ClientSize = new System.Drawing.Size(800, 600);

//Initialize the renderer
GL = new renderX(800, 600, this.Handle);

//Create a buffer from our included cube with uv map primitive
vertexBuffer = new GLBuffer(renderX.PrimitiveTypes.Cube(), 5, MemoryLocation.Heap);
//Initialize the shader
cubeShader = new Shader(CubeVS, CubeFS, GLRenderMode.Triangle);

cameraPosition = new Vector3(0, 0, -100);
cameraRotation = new Vector3(0, 0, 0);

GL.SetMatrixData(90, 160, 0);
GL.ForceCameraPosition(cameraPosition);
GL.ForceCameraRotation(cameraRotation);
GL.SetFaceCulling(true, false);

//create and initialize a timer
Timer timer = new Timer();
timer.Interval = 15;
timer.Tick += timer_Tick;
timer.Start();

Once you run the code you should see this:

UV Example

However, that is just our UV coordinates, so lets add a texture.

To start, add the following lines:

public float Clamp01(float value){
        if (value < 0) return 0f;
        else if (value > 1) return 1f;
        else return value;
}

Next, lets add our texture references at the top:

GLTexture texture2d;
int* TEXTURE_ADDR;
int textureWidthMinusOne, textureHeightMinusOne, textureHeight;

Next up, in the Form load method add these lines to initialize and load a texture:

texture2d = new GLTexture("myTexture.png", MemoryLocation.Heap, DuringLoad.Flip);
TEXTURE_ADDR = (int*)texture2d.GetAddress();

textureHeight = texture2d.Height;
textureWidthMinusOne = texture2d.Width - 1;
textureHeightMinusOne = texture2d.Height - 1;

Lastly, modify your fragment shader to look like this:

unsafe void CubeFS(byte* BGR, float* Attributes, int Index){
        int U = (int)(Clamp01(Attributes[0]) * textureWidthMinusOne);
        int V = (int)(Clamp01(Attributes[1]) * textureHeightMinusOne);

        *((int*)BGR) = TEXTURE_ADDR[U + V * textureHeight];  
}

It is important to clamp your texture, because otherwise your application will crash if you read out side of the buffer.

If everything is done correctly, your form should look like this:

Final