マイペースなプログラミング日記

x86エミュレータやFPGA、WebGLにお熱なd-kamiがマイペースに書くブログ

PSMでテクスチャマッピング

PlayStation Mobile SDKのサンプルに入っているGraphics\TriangleSampleに入ってるtest.pngを使いテクスチャマッピングをしてみた。テクスチャ座標を新たに追加し、VertexBufferのコンストラクタの引数も変えつつ、VertexBufferにテクスチャ座標を渡す。そしてシェーダのどの変数に渡すのかを下記コードで設定している。VertexBufferの1番目(0番目が最初)のデータをa_TexCoordに渡すようにしている。

program.SetAttributeBinding(1, "a_TexCoord");

テクスチャ読み込みは下記コードで行っている。2番目の引数は後で調べる

texture = new Texture2D("/Application/test.png", false);

シェーダにテクスチャ渡すには、ShaderProgramではなくGraphicsContextにテクスチャを設定するらしい

graphics.SetTexture(0, texture);

あとは頂点シェーダでピクセルシェーダに座標とテクスチャ座標を渡す。そういえば、まだ頂点シェーダで座標弄ってない。

void main(float4 in a_Position  : POSITION,
          float2 in a_TexCoord  : TEXCOORD0,
          float4 out v_Position : POSITION,
          float2 out v_TexCoord : TEXCOORD0)
{
    v_Position = a_Position;
    v_TexCoord = a_TexCoord;
}

最後にピクセルシェーダでテクスチャ座標とテクスチャと三角形の色を使い、最終的な色を決定している。

uniform sampler2D Texture0 : TEXUNIT0;

void main(float2 in v_TexCoord : TEXCOORD0,
          float4 out Color : COLOR,
          uniform float4 MaterialColor)
{
    Color = tex2D(Texture0, v_TexCoord) * MaterialColor;
}

以下C#側の全ソースコード

using System;
using System.Collections.Generic;

using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Environment;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;

namespace Triangle
{
    public class AppMain
    {
        private static GraphicsContext graphics;
        private static ShaderProgram program;
        private static VertexBuffer vbuffer;
        private static Texture2D texture;
        private static Vector4 triangleColor = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
        
        public static void Main (string[] args)
        {
            Initialize();

            while(true){
                SystemEvents.CheckEvents();
                Update();
                Render();
            }
        }

        public static void Initialize()
        {
            graphics = new GraphicsContext();
            
            program = new ShaderProgram("/Application/shaders/test.cgx");
            vbuffer = new VertexBuffer(3, VertexFormat.Float3, VertexFormat.Float2);
            texture = new Texture2D("/Application/test.png", false);
            
            program.SetUniformBinding(0, "MaterialColor");
            program.SetAttributeBinding(0, "a_Position");
            program.SetAttributeBinding(1, "a_TexCoord");
            
            float[] positions = {
                0.0f, 0.577f, 0.0f,
                -0.5f, -0.289f, 0.0f,
                0.5f, -0.289f, 0.0f,
            };
            
            float[] texcoords = {
                0.5f, 0.0f,
                0.0f, 1.0f,
                1.0f, 1.0f,
            };
            
            vbuffer.SetVertices(0, positions);
            vbuffer.SetVertices(1, texcoords);
        }

        public static void Update()
        {
            var gamePadData = GamePad.GetData(0);
        }

        public static void Render()
        {
            graphics.SetViewport(0, 0, graphics.Screen.Width, graphics.Screen.Height);
            graphics.SetClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            graphics.Clear();
            
            graphics.SetShaderProgram(program);
            graphics.SetVertexBuffer(0, vbuffer);
            graphics.SetTexture(0, texture);
            
            program.SetUniformValue(0, ref triangleColor);
            
            graphics.DrawArrays(DrawMode.TriangleStrip, 0, 3);
            graphics.SwapBuffers();
        }
    }
}