hello triangle picasso
This commit is contained in:
parent
31502c21fe
commit
d2e9db6c84
170
examples/graphics/hello_triangle/Makefile
Normal file
170
examples/graphics/hello_triangle/Makefile
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
TOPDIR ?= $(CURDIR)
|
||||||
|
include $(DEVKITARM)/3ds_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# DATA is a list of directories containing data files
|
||||||
|
# INCLUDES is a list of directories containing header files
|
||||||
|
#
|
||||||
|
# NO_SMDH: if set to anything, no SMDH file is generated.
|
||||||
|
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
|
||||||
|
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
|
||||||
|
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
|
||||||
|
# ICON is the filename of the icon (.png), relative to the project folder.
|
||||||
|
# If not set, it attempts to use one of the following (in this order):
|
||||||
|
# - <Project name>.png
|
||||||
|
# - icon.png
|
||||||
|
# - <libctru folder>/default_icon.png
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
|
||||||
|
|
||||||
|
CFLAGS := -g -Wall -Wfatal-errors -O2 -mword-relocations \
|
||||||
|
-fomit-frame-pointer -ffast-math \
|
||||||
|
$(ARCH)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS := -lctru -lm
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(CTRULIB)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
ifeq ($(strip $(ICON)),)
|
||||||
|
icons := $(wildcard *.png)
|
||||||
|
ifneq (,$(findstring $(TARGET).png,$(icons)))
|
||||||
|
export APP_ICON := $(TOPDIR)/$(TARGET).png
|
||||||
|
else
|
||||||
|
ifneq (,$(findstring icon.png,$(icons)))
|
||||||
|
export APP_ICON := $(TOPDIR)/icon.png
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
export APP_ICON := $(TOPDIR)/$(ICON)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD)
|
||||||
|
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(NO_SMDH)),)
|
||||||
|
.PHONY: all
|
||||||
|
all : $(OUTPUT).3dsx $(OUTPUT).smdh
|
||||||
|
endif
|
||||||
|
$(OUTPUT).3dsx : $(OUTPUT).elf
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
# WARNING: This is not the right way to do this! TODO: Do it right!
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.vsh.o : %.vsh
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
picasso ../$(notdir $<).shbin $<
|
||||||
|
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
|
||||||
|
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
|
||||||
|
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||||
|
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
|
||||||
|
@rm ../$(notdir $<).shbin
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
4
examples/graphics/hello_triangle/README.md
Normal file
4
examples/graphics/hello_triangle/README.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Hello Triangle
|
||||||
|
|
||||||
|
A simple GPU demo to display a white triangle.
|
||||||
|
Requires the [picasso](https://github.com/fincs/picasso) shader assembler.
|
32
examples/graphics/hello_triangle/data/shader.vsh
Normal file
32
examples/graphics/hello_triangle/data/shader.vsh
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
; Really simple & stupid PICA200 shader
|
||||||
|
; Taken from picasso example
|
||||||
|
|
||||||
|
; Uniforms
|
||||||
|
.fvec projection[4]
|
||||||
|
|
||||||
|
; Constants
|
||||||
|
.constf myconst(0.0, 1.0, -1.0, 0.0)
|
||||||
|
.alias ones myconst.yyyy ; (1.0,1.0,1.0,1.0)
|
||||||
|
|
||||||
|
; Outputs : here only position and color
|
||||||
|
.out outpos position
|
||||||
|
.out outclr color
|
||||||
|
|
||||||
|
; Inputs : here we have only vertices
|
||||||
|
.alias inpos v0
|
||||||
|
|
||||||
|
.proc main
|
||||||
|
; r0 = (inpos.x, inpos.y, inpos.z, 1.0)
|
||||||
|
mov r0.xyz, inpos
|
||||||
|
mov r0.w, ones
|
||||||
|
|
||||||
|
; outpos = projection * r1
|
||||||
|
dp4 outpos.x, projection[0], r0
|
||||||
|
dp4 outpos.y, projection[1], r0
|
||||||
|
dp4 outpos.z, projection[2], r0
|
||||||
|
dp4 outpos.w, projection[3], r0
|
||||||
|
|
||||||
|
; Set vertex color to white
|
||||||
|
mov outclr, ones
|
||||||
|
end
|
||||||
|
.end
|
31
examples/graphics/hello_triangle/source/3dutils.c
Normal file
31
examples/graphics/hello_triangle/source/3dutils.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// Created by Lectem on 22/03/2015.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "3dutils.h"
|
||||||
|
|
||||||
|
void SetUniformMatrix(u32 startreg, float* m) {
|
||||||
|
float param[16];
|
||||||
|
|
||||||
|
param[0x0]=m[3]; //w
|
||||||
|
param[0x1]=m[2]; //z
|
||||||
|
param[0x2]=m[1]; //y
|
||||||
|
param[0x3]=m[0]; //x
|
||||||
|
|
||||||
|
param[0x4]=m[7];
|
||||||
|
param[0x5]=m[6];
|
||||||
|
param[0x6]=m[5];
|
||||||
|
param[0x7]=m[4];
|
||||||
|
|
||||||
|
param[0x8]=m[11];
|
||||||
|
param[0x9]=m[10];
|
||||||
|
param[0xa]=m[9];
|
||||||
|
param[0xb]=m[8];
|
||||||
|
|
||||||
|
param[0xc]=m[15];
|
||||||
|
param[0xd]=m[14];
|
||||||
|
param[0xe]=m[13];
|
||||||
|
param[0xf]=m[12];
|
||||||
|
|
||||||
|
GPU_SetFloatUniform(GPU_VERTEX_SHADER, startreg, (u32*)param, 4);
|
||||||
|
}
|
10
examples/graphics/hello_triangle/source/3dutils.h
Normal file
10
examples/graphics/hello_triangle/source/3dutils.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by Lectem on 22/03/2015.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef _2DGPU_3DUTILS_H_
|
||||||
|
#define _2DGPU_3DUTILS_H_
|
||||||
|
#include <3ds.h>
|
||||||
|
void SetUniformMatrix(u32 startreg, float* m);
|
||||||
|
|
||||||
|
#endif //_2DGPU_3DUTILS_H_
|
246
examples/graphics/hello_triangle/source/main.c
Normal file
246
examples/graphics/hello_triangle/source/main.c
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
#include <3ds.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "shader_vsh_shbin.h"
|
||||||
|
#include "3dutils.h"
|
||||||
|
#include "mmath.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define STRINGIZE(x) STRINGIZE2(x)
|
||||||
|
#define STRINGIZE2(x) #x
|
||||||
|
#define LINE_STRING STRINGIZE(__LINE__)
|
||||||
|
#define my_assert(e) ((e) ? (void)0 : _my_assert("assert failed at " __FILE__ ":" LINE_STRING " (" #e ")\n"))
|
||||||
|
void _my_assert(char * text)
|
||||||
|
{
|
||||||
|
printf("%s\n",text);
|
||||||
|
do{
|
||||||
|
hidScanInput();
|
||||||
|
if(keysDown()&KEY_START)break;
|
||||||
|
gfxFlushBuffers();
|
||||||
|
gfxSwapBuffers();
|
||||||
|
gspWaitForVBlank();
|
||||||
|
}while(aptMainLoop());
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x, y, z;
|
||||||
|
} vector_3f;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float r, g, b, a;
|
||||||
|
} vector_4f;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vector_3f position;
|
||||||
|
vector_4f color;
|
||||||
|
} vertex_pos_col;
|
||||||
|
|
||||||
|
#define GPU_CMD_SIZE 0x40000
|
||||||
|
|
||||||
|
//GPU framebuffer address
|
||||||
|
u32* gpuFBuffer =(u32*)0x1F119400;
|
||||||
|
//GPU depth buffer address
|
||||||
|
u32* gpuDBuffer =(u32*)0x1F370800;
|
||||||
|
|
||||||
|
//GPU command buffers
|
||||||
|
u32* gpuCmd = NULL;
|
||||||
|
|
||||||
|
//shader structure
|
||||||
|
DVLB_s* shader_dvlb; //the header
|
||||||
|
shaderProgram_s shader; //the program
|
||||||
|
|
||||||
|
|
||||||
|
Result projUniformRegister =-1;
|
||||||
|
Result modelviewUniformRegister =-1;
|
||||||
|
|
||||||
|
#define RGBA8(r,g,b,a) ((((r)&0xFF)<<24) | (((g)&0xFF)<<16) | (((b)&0xFF)<<8) | (((a)&0xFF)<<0))
|
||||||
|
|
||||||
|
//The color used to clear the screen
|
||||||
|
u32 clearColor=RGBA8(0x68, 0xB0, 0xD8, 0xFF);
|
||||||
|
|
||||||
|
//The projection matrix
|
||||||
|
static float ortho_matrix[4*4];
|
||||||
|
|
||||||
|
void GPU_SetDummyTexEnv(u8 num);
|
||||||
|
void gpuUIEndFrame();
|
||||||
|
|
||||||
|
void gpuUIInit()
|
||||||
|
{
|
||||||
|
|
||||||
|
GPU_Init(NULL);//initialize GPU
|
||||||
|
|
||||||
|
gfxSet3D(false);//We will not be using the 3D mode in this example
|
||||||
|
Result res=0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load our vertex shader and its uniforms
|
||||||
|
* Check http://3dbrew.org/wiki/SHBIN for more informations about the shader binaries
|
||||||
|
*/
|
||||||
|
shader_dvlb = DVLB_ParseFile((u32 *)shader_vsh_shbin, shader_vsh_shbin_size);//load our vertex shader binary
|
||||||
|
my_assert(shader_dvlb != NULL);
|
||||||
|
shaderProgramInit(&shader);
|
||||||
|
res = shaderProgramSetVsh(&shader, &shader_dvlb->DVLE[0]);
|
||||||
|
my_assert(res >=0); // check for errors
|
||||||
|
|
||||||
|
//In this example we are only rendering in "2D mode", so we don't need one command buffer per eye
|
||||||
|
gpuCmd=(u32*)linearAlloc(GPU_CMD_SIZE * (sizeof *gpuCmd) ); //Don't forget that commands size is 4 (hence the sizeof)
|
||||||
|
my_assert(gpuCmd != NULL);
|
||||||
|
|
||||||
|
//Reset the gpu
|
||||||
|
//This actually needs a command buffer to work, and will then use it as default
|
||||||
|
GPU_Reset(NULL, gpuCmd, GPU_CMD_SIZE);
|
||||||
|
|
||||||
|
projUniformRegister = shaderInstanceGetUniformLocation(shader.vertexShader, "projection");
|
||||||
|
my_assert(projUniformRegister != -1); // make sure we did get the uniform
|
||||||
|
|
||||||
|
|
||||||
|
shaderProgramUse(&shader); // Select the shader to use
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
initOrthographicMatrix(ortho_matrix, 0.0f, 400.0f, 0.0f, 240.0f, 0.0f, 1.0f); // A basic projection for 2D drawings
|
||||||
|
SetUniformMatrix(projUniformRegister, ortho_matrix); // Upload the matrix to the GPU
|
||||||
|
|
||||||
|
//Flush buffers and setup the environment for the next frame
|
||||||
|
gpuUIEndFrame();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpuUIExit()
|
||||||
|
{
|
||||||
|
//do things properly
|
||||||
|
linearFree(gpuCmd);
|
||||||
|
shaderProgramFree(&shader);
|
||||||
|
DVLB_Free(shader_dvlb);
|
||||||
|
GPU_Reset(NULL, gpuCmd, GPU_CMD_SIZE); // Not really needed, but safer for the next applications ?
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpuUIEndFrame()
|
||||||
|
{
|
||||||
|
//Ask the GPU to draw everything (execute the commands)
|
||||||
|
GPU_FinishDrawing();
|
||||||
|
GPUCMD_Finalize();
|
||||||
|
GPUCMD_FlushAndRun(NULL);
|
||||||
|
gspWaitForP3D();
|
||||||
|
//Draw the screen
|
||||||
|
GX_SetDisplayTransfer(NULL, gpuFBuffer, 0x019001E0, (u32*)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 0x019001E0, 0x01001000);
|
||||||
|
gspWaitForPPF();
|
||||||
|
//Clear the screen
|
||||||
|
GX_SetMemoryFill(NULL, gpuFBuffer, clearColor, &gpuFBuffer[0x2EE00],
|
||||||
|
0x201, gpuDBuffer, 0x00000000, &gpuDBuffer[0x2EE00], 0x201);
|
||||||
|
gspWaitForPSC0();
|
||||||
|
gfxSwapBuffersGpu();
|
||||||
|
|
||||||
|
//Wait for the screen to be updated
|
||||||
|
gspWaitForVBlank();
|
||||||
|
|
||||||
|
//Get ready to start a new frame
|
||||||
|
GPUCMD_SetBufferOffset(0);
|
||||||
|
|
||||||
|
//Viewport (http://3dbrew.org/wiki/GPU_Commands#Command_0x0041)
|
||||||
|
GPU_SetViewport((u32 *)osConvertVirtToPhys((u32)gpuDBuffer),
|
||||||
|
(u32 *)osConvertVirtToPhys((u32)gpuFBuffer),
|
||||||
|
0, 0, 240*2, 400); //Our screen is 400*240, and we actually have 2 framebuffers, even without 3D mode activated
|
||||||
|
|
||||||
|
|
||||||
|
GPU_DepthMap(-1.0f, 0.0f); //Be careful, standard OpenGL clipping is [-1;1], but it is [-1;0] on the pica200
|
||||||
|
// Note : this is corrected by our projection matrix !
|
||||||
|
|
||||||
|
//Sets the texture environment parameters not to modify our pixels at fragment stage
|
||||||
|
//See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight
|
||||||
|
GPU_SetTexEnv(
|
||||||
|
0,
|
||||||
|
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||||
|
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR),
|
||||||
|
GPU_TEVOPERANDS(0,0,0),
|
||||||
|
GPU_TEVOPERANDS(0,0,0),
|
||||||
|
GPU_REPLACE, GPU_REPLACE,
|
||||||
|
0xFFFFFFFF
|
||||||
|
);
|
||||||
|
GPU_SetDummyTexEnv(1);
|
||||||
|
GPU_SetDummyTexEnv(2);
|
||||||
|
GPU_SetDummyTexEnv(3);
|
||||||
|
GPU_SetDummyTexEnv(4);
|
||||||
|
GPU_SetDummyTexEnv(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Our data
|
||||||
|
static const vector_3f triangle_mesh[] =
|
||||||
|
{
|
||||||
|
{240.0f+60.0f, 120.0f, 0.5f},
|
||||||
|
{240.0f-60.0f, 120.0f+60.0f, 0.5f},
|
||||||
|
{240.0f-60.0f, 120.0f-60.0f, 0.5f}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void* triangle_data = NULL;
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
srvInit();
|
||||||
|
aptInit();
|
||||||
|
hidInit(NULL);
|
||||||
|
|
||||||
|
gfxInitDefault();
|
||||||
|
consoleInit(GFX_BOTTOM, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
gpuUIInit();
|
||||||
|
printf("hello triangle !\n");
|
||||||
|
triangle_data = linearAlloc(sizeof(triangle_mesh)); //allocate our vbo on the linear heap
|
||||||
|
memcpy(triangle_data, triangle_mesh, sizeof(triangle_mesh)); //Copy our data
|
||||||
|
|
||||||
|
do{
|
||||||
|
hidScanInput();
|
||||||
|
if(keysDown()&KEY_START)break; //Stop the program when Start is pressed
|
||||||
|
|
||||||
|
//Setup the buffers data
|
||||||
|
GPU_SetAttributeBuffers(
|
||||||
|
1, // number of attributes
|
||||||
|
(u32 *) osConvertVirtToPhys((u32) triangle_data),
|
||||||
|
GPU_ATTRIBFMT(0, 3, GPU_FLOAT),//We only have vertices
|
||||||
|
0xFFFE,//Attribute mask, in our case 0b1110
|
||||||
|
0x0,//Attribute permutations (here it is the identity)
|
||||||
|
1, //number of buffers
|
||||||
|
(u32[]) {0x0}, // buffer offsets (placeholders)
|
||||||
|
(u64[]) {0x0}, // attribute permutations for each buffer (identity again)
|
||||||
|
(u8[]) {1} // number of attributes for each buffer
|
||||||
|
);
|
||||||
|
//Display the buffers data
|
||||||
|
GPU_DrawArray(GPU_TRIANGLES, sizeof(triangle_mesh) / sizeof(triangle_mesh[0]));
|
||||||
|
|
||||||
|
gpuUIEndFrame();
|
||||||
|
|
||||||
|
}while(aptMainLoop());
|
||||||
|
gpuUIExit();
|
||||||
|
|
||||||
|
|
||||||
|
gfxExit();
|
||||||
|
hidExit();
|
||||||
|
aptExit();
|
||||||
|
srvExit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GPU_SetDummyTexEnv(u8 num)
|
||||||
|
{
|
||||||
|
//Don't touch the colors of the previous stages
|
||||||
|
GPU_SetTexEnv(num,
|
||||||
|
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||||
|
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
|
||||||
|
GPU_TEVOPERANDS(0,0,0),
|
||||||
|
GPU_TEVOPERANDS(0,0,0),
|
||||||
|
GPU_REPLACE,
|
||||||
|
GPU_REPLACE,
|
||||||
|
0xFFFFFFFF);
|
||||||
|
}
|
203
examples/graphics/hello_triangle/source/mmath.c
Normal file
203
examples/graphics/hello_triangle/source/mmath.c
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <3ds.h>
|
||||||
|
#include "mmath.h"
|
||||||
|
|
||||||
|
void loadIdentity44(float* m)
|
||||||
|
{
|
||||||
|
if(!m)return;
|
||||||
|
|
||||||
|
memset(m, 0x00, 16*4);
|
||||||
|
m[0]=m[5]=m[10]=m[15]=1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void multMatrix44(float* m1, float* m2, float* m) //4x4
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for(i=0;i<4;i++)for(j=0;j<4;j++)m[i+j*4]=(m1[0+j*4]*m2[i+0*4])+(m1[1+j*4]*m2[i+1*4])+(m1[2+j*4]*m2[i+2*4])+(m1[3+j*4]*m2[i+3*4]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void translateMatrix(float* tm, float x, float y, float z)
|
||||||
|
{
|
||||||
|
float rm[16], m[16];
|
||||||
|
|
||||||
|
loadIdentity44(rm);
|
||||||
|
rm[3]=x;
|
||||||
|
rm[7]=y;
|
||||||
|
rm[11]=z;
|
||||||
|
|
||||||
|
multMatrix44(tm,rm,m);
|
||||||
|
memcpy(tm,m,16*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 00 01 02 03
|
||||||
|
// 04 05 06 07
|
||||||
|
// 08 09 10 11
|
||||||
|
// 12 13 14 15
|
||||||
|
|
||||||
|
void rotateMatrixX(float* tm, float x, bool r)
|
||||||
|
{
|
||||||
|
float rm[16], m[16];
|
||||||
|
memset(rm, 0x00, 16*4);
|
||||||
|
rm[0]=1.0f;
|
||||||
|
rm[5]=cos(x);
|
||||||
|
rm[6]=sin(x);
|
||||||
|
rm[9]=-sin(x);
|
||||||
|
rm[10]=cos(x);
|
||||||
|
rm[15]=1.0f;
|
||||||
|
if(!r)multMatrix44(tm,rm,m);
|
||||||
|
else multMatrix44(rm,tm,m);
|
||||||
|
memcpy(tm,m,16*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotateMatrixY(float* tm, float x, bool r)
|
||||||
|
{
|
||||||
|
float rm[16], m[16];
|
||||||
|
memset(rm, 0x00, 16*4);
|
||||||
|
rm[0]=cos(x);
|
||||||
|
rm[2]=sin(x);
|
||||||
|
rm[5]=1.0f;
|
||||||
|
rm[8]=-sin(x);
|
||||||
|
rm[10]=cos(x);
|
||||||
|
rm[15]=1.0f;
|
||||||
|
if(!r)multMatrix44(tm,rm,m);
|
||||||
|
else multMatrix44(rm,tm,m);
|
||||||
|
memcpy(tm,m,16*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotateMatrixZ(float* tm, float x, bool r)
|
||||||
|
{
|
||||||
|
float rm[16], m[16];
|
||||||
|
memset(rm, 0x00, 16*4);
|
||||||
|
rm[0]=cos(x);
|
||||||
|
rm[1]=sin(x);
|
||||||
|
rm[4]=-sin(x);
|
||||||
|
rm[5]=cos(x);
|
||||||
|
rm[10]=1.0f;
|
||||||
|
rm[15]=1.0f;
|
||||||
|
if(!r)multMatrix44(tm,rm,m);
|
||||||
|
else multMatrix44(rm,tm,m);
|
||||||
|
memcpy(tm,m,16*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
void scaleMatrix(float* tm, float x, float y, float z)
|
||||||
|
{
|
||||||
|
tm[0]*=x; tm[4]*=x; tm[8]*=x; tm[12]*=x;
|
||||||
|
tm[1]*=y; tm[5]*=y; tm[9]*=y; tm[13]*=y;
|
||||||
|
tm[2]*=z; tm[6]*=z; tm[10]*=z; tm[14]*=z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initProjectionMatrix(float* m, float fovy, float aspect, float near, float far)
|
||||||
|
{
|
||||||
|
float top = near*tan(fovy/2);
|
||||||
|
float right = (top*aspect);
|
||||||
|
|
||||||
|
float mp[4*4];
|
||||||
|
|
||||||
|
mp[0x0] = near/right;
|
||||||
|
mp[0x1] = 0.0f;
|
||||||
|
mp[0x2] = 0.0f;
|
||||||
|
mp[0x3] = 0.0f;
|
||||||
|
|
||||||
|
mp[0x4] = 0.0f;
|
||||||
|
mp[0x5] = near/top;
|
||||||
|
mp[0x6] = 0.0f;
|
||||||
|
mp[0x7] = 0.0f;
|
||||||
|
|
||||||
|
mp[0x8] = 0.0f;
|
||||||
|
mp[0x9] = 0.0f;
|
||||||
|
mp[0xA] = -(far+near)/(far-near);
|
||||||
|
mp[0xB] = -2.0f*(far*near)/(far-near);
|
||||||
|
|
||||||
|
mp[0xC] = 0.0f;
|
||||||
|
mp[0xD] = 0.0f;
|
||||||
|
mp[0xE] = -1.0f;
|
||||||
|
mp[0xF] = 0.0f;
|
||||||
|
|
||||||
|
float mp2[4*4];
|
||||||
|
loadIdentity44(mp2);
|
||||||
|
mp2[0xA]=0.5;
|
||||||
|
mp2[0xB]=-0.5;
|
||||||
|
|
||||||
|
multMatrix44(mp2, mp, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initOrthographicMatrix(float *m, float left, float right, float bottom, float top, float near, float far)
|
||||||
|
{
|
||||||
|
/* ______________________
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
|______________________| ^
|
||||||
|
| x
|
||||||
|
<-----
|
||||||
|
y
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Mirror
|
||||||
|
//right = 400-right;
|
||||||
|
//left = 400-left;
|
||||||
|
//top = 240-top;
|
||||||
|
//bottom = 240-bottom;
|
||||||
|
|
||||||
|
float mp[4*4];
|
||||||
|
|
||||||
|
mp[0x0] = 2.0f/(right-left);
|
||||||
|
mp[0x1] = 0.0f;
|
||||||
|
mp[0x2] = 0.0f;
|
||||||
|
mp[0x3] = -(right+left)/(right-left);
|
||||||
|
|
||||||
|
mp[0x4] = 0.0f;
|
||||||
|
mp[0x5] = 2.0f/(top-bottom);
|
||||||
|
mp[0x6] = 0.0f;
|
||||||
|
mp[0x7] = -(top+bottom)/(top-bottom);
|
||||||
|
|
||||||
|
mp[0x8] = 0.0f;
|
||||||
|
mp[0x9] = 0.0f;
|
||||||
|
mp[0xA] = -2.0f/(far-near);
|
||||||
|
mp[0xB] = (far+near)/(far-near);
|
||||||
|
|
||||||
|
mp[0xC] = 0.0f;
|
||||||
|
mp[0xD] = 0.0f;
|
||||||
|
mp[0xE] = 0.0f;
|
||||||
|
mp[0xF] = 1.0f;
|
||||||
|
|
||||||
|
float mp2[4*4];
|
||||||
|
loadIdentity44(mp2);
|
||||||
|
mp2[0xA] = 0.5;
|
||||||
|
mp2[0xB] = -0.5;
|
||||||
|
|
||||||
|
//Convert Z [-1, 1] to [-1, 0] (PICA shiz)
|
||||||
|
multMatrix44(mp2, mp, m);
|
||||||
|
|
||||||
|
//rotateMatrixZ(m, M_PI/2, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
vect3Df_s getMatrixColumn(float* m, u8 i)
|
||||||
|
{
|
||||||
|
if(!m || i>=4)return vect3Df(0,0,0);
|
||||||
|
return vect3Df(m[0+i*4],m[1+i*4],m[2+i*4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vect3Df_s getMatrixRow(float* m, u8 i)
|
||||||
|
{
|
||||||
|
if(!m || i>=4)return vect3Df(0,0,0);
|
||||||
|
return vect3Df(m[i+0*4],m[i+1*4],m[i+2*4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vect4Df_s getMatrixColumn4(float* m, u8 i)
|
||||||
|
{
|
||||||
|
if(!m || i>=4)return vect4Df(0,0,0,0);
|
||||||
|
return vect4Df(m[0+i*4],m[1+i*4],m[2+i*4],m[3+i*4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vect4Df_s getMatrixRow4(float* m, u8 i)
|
||||||
|
{
|
||||||
|
if(!m || i>=4)return vect4Df(0,0,0,0);
|
||||||
|
return vect4Df(m[i+0*4],m[i+1*4],m[i+2*4],m[i+3*4]);
|
||||||
|
}
|
152
examples/graphics/hello_triangle/source/mmath.h
Normal file
152
examples/graphics/hello_triangle/source/mmath.h
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#ifndef MATH_H
|
||||||
|
#define MATH_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <3ds/types.h>
|
||||||
|
#include <math.h>
|
||||||
|
#pragma GCC diagnostic ignored "-Wnarrowing"
|
||||||
|
|
||||||
|
|
||||||
|
typedef float mtx44[4][4];
|
||||||
|
typedef float mtx33[3][3];
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s32 x, y, z;
|
||||||
|
}vect3Di_s;
|
||||||
|
|
||||||
|
static inline vect3Di_s vect3Di(s32 x, s32 y, s32 z)
|
||||||
|
{
|
||||||
|
return (vect3Di_s){x,y,z};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Di_s vaddi(vect3Di_s u, vect3Di_s v)
|
||||||
|
{
|
||||||
|
return (vect3Di_s){u.x+v.x,u.y+v.y,u.z+v.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Di_s vsubi(vect3Di_s u, vect3Di_s v)
|
||||||
|
{
|
||||||
|
return (vect3Di_s){u.x-v.x,u.y-v.y,u.z-v.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Di_s vmuli(vect3Di_s v, s32 f)
|
||||||
|
{
|
||||||
|
return (vect3Di_s){v.x*f,v.y*f,v.z*f};
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
}vect3Df_s;
|
||||||
|
|
||||||
|
static inline vect3Df_s vect3Df(float x, float y, float z)
|
||||||
|
{
|
||||||
|
return (vect3Df_s){x,y,z};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Df_s vaddf(vect3Df_s u, vect3Df_s v)
|
||||||
|
{
|
||||||
|
return (vect3Df_s){u.x+v.x,u.y+v.y,u.z+v.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Df_s vsubf(vect3Df_s u, vect3Df_s v)
|
||||||
|
{
|
||||||
|
return (vect3Df_s){u.x-v.x,u.y-v.y,u.z-v.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Df_s vmulf(vect3Df_s v, float f)
|
||||||
|
{
|
||||||
|
return (vect3Df_s){v.x*f,v.y*f,v.z*f};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Df_s vscalef(vect3Df_s v1, vect3Df_s v2)
|
||||||
|
{
|
||||||
|
return (vect3Df_s){v1.x*v2.x,v1.y*v2.y,v1.z*v2.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float vmagf(vect3Df_s v)
|
||||||
|
{
|
||||||
|
return sqrtf(v.x*v.x+v.y*v.y+v.z*v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float vdistf(vect3Df_s v1, vect3Df_s v2)
|
||||||
|
{
|
||||||
|
return sqrtf((v1.x-v2.x)*(v1.x-v2.x)+(v1.y-v2.y)*(v1.y-v2.y)+(v1.z-v2.z)*(v1.z-v2.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Df_s vnormf(vect3Df_s v)
|
||||||
|
{
|
||||||
|
const float l=sqrtf(v.x*v.x+v.y*v.y+v.z*v.z);
|
||||||
|
return (vect3Df_s){v.x/l,v.y/l,v.z/l};
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float x, y, z, w;
|
||||||
|
}vect4Df_s;
|
||||||
|
|
||||||
|
static inline vect4Df_s vect4Df(float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
return (vect4Df_s){x,y,z,w};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect4Df_s vaddf4(vect4Df_s u, vect4Df_s v)
|
||||||
|
{
|
||||||
|
return (vect4Df_s){u.x+v.x,u.y+v.y,u.z+v.z,u.w+v.w};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect4Df_s vsubf4(vect4Df_s u, vect4Df_s v)
|
||||||
|
{
|
||||||
|
return (vect4Df_s){u.x-v.x,u.y-v.y,u.z-v.z,u.w-v.w};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect4Df_s vmulf4(vect4Df_s v, float f)
|
||||||
|
{
|
||||||
|
return (vect4Df_s){v.x*f,v.y*f,v.z*f,v.w*f};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float vdotf4(vect4Df_s v1, vect4Df_s v2)
|
||||||
|
{
|
||||||
|
return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z+v1.w*v2.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect4Df_s vnormf4(vect4Df_s v)
|
||||||
|
{
|
||||||
|
const float l=sqrtf(v.x*v.x+v.y*v.y+v.z*v.z+v.w*v.w);
|
||||||
|
return (vect4Df_s){v.x/l,v.y/l,v.z/l,v.w/l};
|
||||||
|
}
|
||||||
|
|
||||||
|
//interstuff
|
||||||
|
static inline vect3Di_s vf2i(vect3Df_s v)
|
||||||
|
{
|
||||||
|
return (vect3Di_s){floorf(v.x),floorf(v.y),floorf(v.z)};
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vect3Df_s vi2f(vect3Di_s v)
|
||||||
|
{
|
||||||
|
return (vect3Df_s){(float)v.x,(float)v.y,(float)v.z};
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadIdentity44(float* m);
|
||||||
|
void multMatrix44(float* m1, float* m2, float* m);
|
||||||
|
|
||||||
|
void translateMatrix(float* tm, float x, float y, float z);
|
||||||
|
void rotateMatrixX(float* tm, float x, bool r);
|
||||||
|
void rotateMatrixY(float* tm, float x, bool r);
|
||||||
|
void rotateMatrixZ(float* tm, float x, bool r);
|
||||||
|
void scaleMatrix(float* tm, float x, float y, float z);
|
||||||
|
|
||||||
|
void initProjectionMatrix(float* m, float fovy, float aspect, float near, float far);
|
||||||
|
void initOrthographicMatrix(float *m, float left, float right, float bottom, float top, float near, float far);
|
||||||
|
|
||||||
|
|
||||||
|
vect3Df_s getMatrixColumn(float* m, u8 i);
|
||||||
|
vect3Df_s getMatrixRow(float* m, u8 i);
|
||||||
|
vect4Df_s getMatrixColumn4(float* m, u8 i);
|
||||||
|
vect4Df_s getMatrixRow4(float* m, u8 i);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user