From f59987301c15657016a5a3838d41e1bdea4316e1 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 27 Dec 2014 15:53:21 +0100 Subject: [PATCH 01/16] 1st attempt to install dkA and build --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e19974f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: cpp + +before_install: + - wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl/download + +install: + - perl devkitARMupdate.pl + +script: + - cd libctru + - make \ No newline at end of file From 943fb0f8a786f73f9a7016e27bcf91afb687ec3b Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 27 Dec 2014 15:56:13 +0100 Subject: [PATCH 02/16] sudo might help --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e19974f..ae07b30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ before_install: - wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl/download install: - - perl devkitARMupdate.pl + - sudo perl devkitARMupdate.pl script: - cd libctru From 8b12d3d82777d1e9382d7c640826c53965cc9157 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 27 Dec 2014 15:59:26 +0100 Subject: [PATCH 03/16] language changed to c --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ae07b30..71635eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: cpp +language: c before_install: - wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl/download From 374bb2207611a1bcfcab9b9e0e9ddefc98277ea3 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 27 Dec 2014 16:02:09 +0100 Subject: [PATCH 04/16] fixed wget name download issue --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 71635eb..bb6c332 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: c before_install: - - wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl/download + - wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl install: - sudo perl devkitARMupdate.pl From aada32fdf21fc68a5e923d8a81392e02b3c1f6fd Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 27 Dec 2014 16:05:01 +0100 Subject: [PATCH 05/16] added env vars --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index bb6c332..c2e5193 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: c before_install: - wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl + - export DEVKITPRO=/home/travis/devkitPro + - export DEVKITARM=${DEVKITPRO}/devkitARM install: - sudo perl devkitARMupdate.pl From a4a4f7b4a0578392984481b2f003e8aebebd4368 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 27 Dec 2014 16:08:48 +0100 Subject: [PATCH 06/16] Added the build status (pre replaced with a future smealum travis) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59d8261..f628817 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -ctrulib +ctrulib[![Build Status](https://travis-ci.org/smealum/ctrulib.svg?branch=master)](https://travis-ci.org/smealum/ctrulib) ======= CTR User Library From d8ddd15287e4890ab64835190f4319be66638175 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 21 Mar 2015 14:32:56 +0100 Subject: [PATCH 07/16] test doc generation --- .gitignore | 1 + .travis.yml | 19 ++++++++++++++++++- exportdoc.sh | 12 ++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 exportdoc.sh diff --git a/.gitignore b/.gitignore index 0a8db49..f9bfa40 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ Thumbs.db build/ lib/ +docs/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index c2e5193..c2fb70b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,10 +4,27 @@ before_install: - wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl - export DEVKITPRO=/home/travis/devkitPro - export DEVKITARM=${DEVKITPRO}/devkitARM + - sudo add-apt-repository --yes ppa:libreoffice/ppa + - sudo apt-get update -qq install: - sudo perl devkitARMupdate.pl + +env: + global: + - secure: "O+zG6TSo9y2XQOUn8n+LcOIKg40ONpLgdZDYPnGjKM+OYp5dffLUjIWQj7PCknhL7HO+fObLGroLvDI7lWOvD81FhsTl5axGxt8NrtslfAnv6SIBom4dww1acqHTo0C1le1+mdhbB1anm7gYCAdDn3TApWBWbGkAOCkS5JzwqC4=" + + script: - cd libctru - - make \ No newline at end of file + - make + - cd .. + + +after_success: + - #Build the doxygen files and upload to GH pages + - git config --global user.email "travis@travis-ci.org" + - git config --global user.name "TravisCI-DocBuilder" + - #export doc only once, in gcc job + - sh exportdoc.sh \ No newline at end of file diff --git a/exportdoc.sh b/exportdoc.sh new file mode 100644 index 0000000..182ea03 --- /dev/null +++ b/exportdoc.sh @@ -0,0 +1,12 @@ +#!/bin/sh +if [ "$CC" = "clang" ] && [ "$TRAVIS_REPO_SLUG" = "Lectem/ctrulib" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then +sudo apt-get install -qq doxygen +git clone --branch=gh-pages --single-branch --depth 1 https://${GH_TOKEN}@github.com/Lectem/ctrulib docs +doxygen Doxyfile +cd docs +git rm -rf ./* +git add --all +git commit -m"Doc generated from Travis build #$TRAVIS_BUILD_NUMBER" +git push -f origin gh-pages + +fi \ No newline at end of file From 222bc24165576899786f6dff5d54ce09c1882c4c Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 21 Mar 2015 15:23:17 +0100 Subject: [PATCH 08/16] forgot to remove a condition --- exportdoc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exportdoc.sh b/exportdoc.sh index 182ea03..6793efb 100644 --- a/exportdoc.sh +++ b/exportdoc.sh @@ -1,5 +1,5 @@ #!/bin/sh -if [ "$CC" = "clang" ] && [ "$TRAVIS_REPO_SLUG" = "Lectem/ctrulib" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then +if [ "$TRAVIS_REPO_SLUG" = "Lectem/ctrulib" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then sudo apt-get install -qq doxygen git clone --branch=gh-pages --single-branch --depth 1 https://${GH_TOKEN}@github.com/Lectem/ctrulib docs doxygen Doxyfile From 53f307836a8c35b2ec8e8cd6636581178d07bb24 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 21 Mar 2015 15:28:25 +0100 Subject: [PATCH 09/16] fix doxyfile path --- exportdoc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exportdoc.sh b/exportdoc.sh index 6793efb..7d4942a 100644 --- a/exportdoc.sh +++ b/exportdoc.sh @@ -2,7 +2,7 @@ if [ "$TRAVIS_REPO_SLUG" = "Lectem/ctrulib" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then sudo apt-get install -qq doxygen git clone --branch=gh-pages --single-branch --depth 1 https://${GH_TOKEN}@github.com/Lectem/ctrulib docs -doxygen Doxyfile +doxygen libctru/Doxyfile cd docs git rm -rf ./* git add --all From 30e407a013a5db6ed185adafbd63d90f25fa25a9 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 21 Mar 2015 15:41:04 +0100 Subject: [PATCH 10/16] new secure token --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c2fb70b..8e04ad5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,7 @@ install: env: global: - - secure: "O+zG6TSo9y2XQOUn8n+LcOIKg40ONpLgdZDYPnGjKM+OYp5dffLUjIWQj7PCknhL7HO+fObLGroLvDI7lWOvD81FhsTl5axGxt8NrtslfAnv6SIBom4dww1acqHTo0C1le1+mdhbB1anm7gYCAdDn3TApWBWbGkAOCkS5JzwqC4=" - + - secure: "Hayg1mC1ejZWoTC3vl4sv8TNCLGMYC4kxjzectUBQLPve0abgekTUm7wAkYoBo9CecbVnDqMH4sUazR46uZmtji/xeXVc1++9m/r1A7kubsJJsEMi1e5VYaKkpDc+/FycClaSyojwiv69EjtAaHhAld7qmu+zN/pJZNTbmX071Y=" script: - cd libctru From 51deccd4d0f15d81695dfa2f8aacfcee3bcce985 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 21 Mar 2015 15:47:06 +0100 Subject: [PATCH 11/16] fixed docs clean order --- exportdoc.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/exportdoc.sh b/exportdoc.sh index 7d4942a..0880dd1 100644 --- a/exportdoc.sh +++ b/exportdoc.sh @@ -2,9 +2,12 @@ if [ "$TRAVIS_REPO_SLUG" = "Lectem/ctrulib" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ]; then sudo apt-get install -qq doxygen git clone --branch=gh-pages --single-branch --depth 1 https://${GH_TOKEN}@github.com/Lectem/ctrulib docs -doxygen libctru/Doxyfile cd docs git rm -rf ./* +cd .. +doxygen libctru/Doxyfile +cd docs +mv ./html/* . git add --all git commit -m"Doc generated from Travis build #$TRAVIS_BUILD_NUMBER" git push -f origin gh-pages From 31502c21fe8502783ac6df8654bc052a5d99da09 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sat, 21 Mar 2015 15:55:40 +0100 Subject: [PATCH 12/16] reverted readme to use my travis build --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f628817..1f25744 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -ctrulib[![Build Status](https://travis-ci.org/smealum/ctrulib.svg?branch=master)](https://travis-ci.org/smealum/ctrulib) +ctrulib[![Build Status](https://travis-ci.org/Lectem/ctrulib.svg?branch=master)](https://travis-ci.org/Lectem/ctrulib) ======= CTR User Library From d2e9db6c8404b76a338ec83e9413cd0b87384a67 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sun, 22 Mar 2015 15:48:25 +0100 Subject: [PATCH 13/16] hello triangle picasso --- examples/graphics/hello_triangle/Makefile | 170 ++++++++++++ examples/graphics/hello_triangle/README.md | 4 + .../graphics/hello_triangle/data/shader.vsh | 32 +++ .../graphics/hello_triangle/source/3dutils.c | 31 +++ .../graphics/hello_triangle/source/3dutils.h | 10 + .../graphics/hello_triangle/source/main.c | 246 ++++++++++++++++++ .../graphics/hello_triangle/source/mmath.c | 203 +++++++++++++++ .../graphics/hello_triangle/source/mmath.h | 152 +++++++++++ 8 files changed, 848 insertions(+) create mode 100644 examples/graphics/hello_triangle/Makefile create mode 100644 examples/graphics/hello_triangle/README.md create mode 100644 examples/graphics/hello_triangle/data/shader.vsh create mode 100644 examples/graphics/hello_triangle/source/3dutils.c create mode 100644 examples/graphics/hello_triangle/source/3dutils.h create mode 100644 examples/graphics/hello_triangle/source/main.c create mode 100644 examples/graphics/hello_triangle/source/mmath.c create mode 100644 examples/graphics/hello_triangle/source/mmath.h diff --git a/examples/graphics/hello_triangle/Makefile b/examples/graphics/hello_triangle/Makefile new file mode 100644 index 0000000..150cce9 --- /dev/null +++ b/examples/graphics/hello_triangle/Makefile @@ -0,0 +1,170 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=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): +# - .png +# - icon.png +# - /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 +#--------------------------------------------------------------------------------------- diff --git a/examples/graphics/hello_triangle/README.md b/examples/graphics/hello_triangle/README.md new file mode 100644 index 0000000..00535b6 --- /dev/null +++ b/examples/graphics/hello_triangle/README.md @@ -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. \ No newline at end of file diff --git a/examples/graphics/hello_triangle/data/shader.vsh b/examples/graphics/hello_triangle/data/shader.vsh new file mode 100644 index 0000000..d86c35a --- /dev/null +++ b/examples/graphics/hello_triangle/data/shader.vsh @@ -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 \ No newline at end of file diff --git a/examples/graphics/hello_triangle/source/3dutils.c b/examples/graphics/hello_triangle/source/3dutils.c new file mode 100644 index 0000000..45215b8 --- /dev/null +++ b/examples/graphics/hello_triangle/source/3dutils.c @@ -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); +} diff --git a/examples/graphics/hello_triangle/source/3dutils.h b/examples/graphics/hello_triangle/source/3dutils.h new file mode 100644 index 0000000..9e3f859 --- /dev/null +++ b/examples/graphics/hello_triangle/source/3dutils.h @@ -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_ diff --git a/examples/graphics/hello_triangle/source/main.c b/examples/graphics/hello_triangle/source/main.c new file mode 100644 index 0000000..fe6f25a --- /dev/null +++ b/examples/graphics/hello_triangle/source/main.c @@ -0,0 +1,246 @@ +#include <3ds.h> +#include +#include +#include +#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); +} \ No newline at end of file diff --git a/examples/graphics/hello_triangle/source/mmath.c b/examples/graphics/hello_triangle/source/mmath.c new file mode 100644 index 0000000..e7715d1 --- /dev/null +++ b/examples/graphics/hello_triangle/source/mmath.c @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#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]); +} diff --git a/examples/graphics/hello_triangle/source/mmath.h b/examples/graphics/hello_triangle/source/mmath.h new file mode 100644 index 0000000..370b3c2 --- /dev/null +++ b/examples/graphics/hello_triangle/source/mmath.h @@ -0,0 +1,152 @@ +#ifndef MATH_H +#define MATH_H +#ifdef __cplusplus +extern "C" { +#endif +#include <3ds/types.h> +#include +#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 From 80a41c8e20b8893f9a3671f00066e7126938dd81 Mon Sep 17 00:00:00 2001 From: Lectem Date: Sun, 22 Mar 2015 15:48:25 +0100 Subject: [PATCH 14/16] hello triangle picasso --- examples/graphics/hello_triangle/Makefile | 170 ++++++++++++ examples/graphics/hello_triangle/README.md | 4 + .../graphics/hello_triangle/data/shader.vsh | 32 +++ .../graphics/hello_triangle/source/3dutils.c | 31 +++ .../graphics/hello_triangle/source/3dutils.h | 10 + .../graphics/hello_triangle/source/main.c | 246 ++++++++++++++++++ .../graphics/hello_triangle/source/mmath.c | 203 +++++++++++++++ .../graphics/hello_triangle/source/mmath.h | 152 +++++++++++ 8 files changed, 848 insertions(+) create mode 100644 examples/graphics/hello_triangle/Makefile create mode 100644 examples/graphics/hello_triangle/README.md create mode 100644 examples/graphics/hello_triangle/data/shader.vsh create mode 100644 examples/graphics/hello_triangle/source/3dutils.c create mode 100644 examples/graphics/hello_triangle/source/3dutils.h create mode 100644 examples/graphics/hello_triangle/source/main.c create mode 100644 examples/graphics/hello_triangle/source/mmath.c create mode 100644 examples/graphics/hello_triangle/source/mmath.h diff --git a/examples/graphics/hello_triangle/Makefile b/examples/graphics/hello_triangle/Makefile new file mode 100644 index 0000000..150cce9 --- /dev/null +++ b/examples/graphics/hello_triangle/Makefile @@ -0,0 +1,170 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=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): +# - .png +# - icon.png +# - /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 +#--------------------------------------------------------------------------------------- diff --git a/examples/graphics/hello_triangle/README.md b/examples/graphics/hello_triangle/README.md new file mode 100644 index 0000000..00535b6 --- /dev/null +++ b/examples/graphics/hello_triangle/README.md @@ -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. \ No newline at end of file diff --git a/examples/graphics/hello_triangle/data/shader.vsh b/examples/graphics/hello_triangle/data/shader.vsh new file mode 100644 index 0000000..d86c35a --- /dev/null +++ b/examples/graphics/hello_triangle/data/shader.vsh @@ -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 \ No newline at end of file diff --git a/examples/graphics/hello_triangle/source/3dutils.c b/examples/graphics/hello_triangle/source/3dutils.c new file mode 100644 index 0000000..45215b8 --- /dev/null +++ b/examples/graphics/hello_triangle/source/3dutils.c @@ -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); +} diff --git a/examples/graphics/hello_triangle/source/3dutils.h b/examples/graphics/hello_triangle/source/3dutils.h new file mode 100644 index 0000000..9e3f859 --- /dev/null +++ b/examples/graphics/hello_triangle/source/3dutils.h @@ -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_ diff --git a/examples/graphics/hello_triangle/source/main.c b/examples/graphics/hello_triangle/source/main.c new file mode 100644 index 0000000..fe6f25a --- /dev/null +++ b/examples/graphics/hello_triangle/source/main.c @@ -0,0 +1,246 @@ +#include <3ds.h> +#include +#include +#include +#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); +} \ No newline at end of file diff --git a/examples/graphics/hello_triangle/source/mmath.c b/examples/graphics/hello_triangle/source/mmath.c new file mode 100644 index 0000000..e7715d1 --- /dev/null +++ b/examples/graphics/hello_triangle/source/mmath.c @@ -0,0 +1,203 @@ +#include +#include +#include +#include +#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]); +} diff --git a/examples/graphics/hello_triangle/source/mmath.h b/examples/graphics/hello_triangle/source/mmath.h new file mode 100644 index 0000000..370b3c2 --- /dev/null +++ b/examples/graphics/hello_triangle/source/mmath.h @@ -0,0 +1,152 @@ +#ifndef MATH_H +#define MATH_H +#ifdef __cplusplus +extern "C" { +#endif +#include <3ds/types.h> +#include +#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 From 56556baaa7b39f3000a08ff03569ca355f8c365c Mon Sep 17 00:00:00 2001 From: Lectem Date: Mon, 23 Mar 2015 23:54:46 +0100 Subject: [PATCH 15/16] bit more comments --- .../graphics/hello_triangle/source/main.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/examples/graphics/hello_triangle/source/main.c b/examples/graphics/hello_triangle/source/main.c index fe6f25a..872a5de 100644 --- a/examples/graphics/hello_triangle/source/main.c +++ b/examples/graphics/hello_triangle/source/main.c @@ -7,6 +7,10 @@ #include "mmath.h" + +/** +* Crappy assert stuff that lets you go back to hbmenu by pressing start. +*/ #define STRINGIZE(x) STRINGIZE2(x) #define STRINGIZE2(x) #x #define LINE_STRING STRINGIZE(__LINE__) @@ -21,7 +25,7 @@ void _my_assert(char * text) gfxSwapBuffers(); gspWaitForVBlank(); }while(aptMainLoop()); - exit(0); + //should stop the program and clean up our mess } @@ -127,10 +131,12 @@ void gpuUIEndFrame() GPU_FinishDrawing(); GPUCMD_Finalize(); GPUCMD_FlushAndRun(NULL); - gspWaitForP3D(); - //Draw the screen + gspWaitForP3D();//Wait for the gpu 3d processing to be done + //Copy the GPU output buffer to the screen framebuffer + //See http://3dbrew.org/wiki/GPU#Transfer_Engine for more details about the transfer engine 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); @@ -146,7 +152,10 @@ void gpuUIEndFrame() //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 + 0, 0, + //Our screen is 400*240, but the GPU actually renders to 400*480 and then downscales it SetDisplayTransfer bit 24 is set + //This is the case here (See http://3dbrew.org/wiki/GPU#0x1EF00C10 for more details) + 240*2, 400); GPU_DepthMap(-1.0f, 0.0f); //Be careful, standard OpenGL clipping is [-1;1], but it is [-1;0] on the pica200 @@ -207,7 +216,7 @@ int main(int argc, char** argv) 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 + 0xFFFE,//Attribute mask, in our case 0b1110 since we use only the first one 0x0,//Attribute permutations (here it is the identity) 1, //number of buffers (u32[]) {0x0}, // buffer offsets (placeholders) From 134f27f520805f08942c967ea24e1937354b119d Mon Sep 17 00:00:00 2001 From: Lectem Date: Tue, 24 Mar 2015 00:11:52 +0100 Subject: [PATCH 16/16] last bit of modif --- .../graphics/hello_triangle/data/shader.vsh | 2 +- .../graphics/hello_triangle/source/main.c | 37 ++++++++++++------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/examples/graphics/hello_triangle/data/shader.vsh b/examples/graphics/hello_triangle/data/shader.vsh index d86c35a..57a694c 100644 --- a/examples/graphics/hello_triangle/data/shader.vsh +++ b/examples/graphics/hello_triangle/data/shader.vsh @@ -26,7 +26,7 @@ dp4 outpos.z, projection[2], r0 dp4 outpos.w, projection[3], r0 - ; Set vertex color to white + ; Set vertex color to white rgba => (1.0,1.0,1.0,1.0) mov outclr, ones end .end \ No newline at end of file diff --git a/examples/graphics/hello_triangle/source/main.c b/examples/graphics/hello_triangle/source/main.c index 872a5de..551048e 100644 --- a/examples/graphics/hello_triangle/source/main.c +++ b/examples/graphics/hello_triangle/source/main.c @@ -1,3 +1,14 @@ +/** +* Hello Triangle example, made by Lectem +* +* Draws a white triangle using the 3DS GPU. +* This example should give you enough hints and links on how to use the GPU for basic non-textured rendering. +* Another version of this example will be made with colors. +* +* Thanks to smea, fincs, neobrain, xerpi and all those who helped me understand how the 3DS GPU works +*/ + + #include <3ds.h> #include #include @@ -133,10 +144,10 @@ void gpuUIEndFrame() GPUCMD_FlushAndRun(NULL); gspWaitForP3D();//Wait for the gpu 3d processing to be done //Copy the GPU output buffer to the screen framebuffer - //See http://3dbrew.org/wiki/GPU#Transfer_Engine for more details about the transfer engine + //See http://3dbrew.org/wiki/GPU#Transfer_Engine for more details about the transfer engine 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); @@ -152,10 +163,10 @@ void gpuUIEndFrame() //Viewport (http://3dbrew.org/wiki/GPU_Commands#Command_0x0041) GPU_SetViewport((u32 *)osConvertVirtToPhys((u32)gpuDBuffer), (u32 *)osConvertVirtToPhys((u32)gpuFBuffer), - 0, 0, - //Our screen is 400*240, but the GPU actually renders to 400*480 and then downscales it SetDisplayTransfer bit 24 is set - //This is the case here (See http://3dbrew.org/wiki/GPU#0x1EF00C10 for more details) - 240*2, 400); + 0, 0, + //Our screen is 400*240, but the GPU actually renders to 400*480 and then downscales it SetDisplayTransfer bit 24 is set + //This is the case here (See http://3dbrew.org/wiki/GPU#0x1EF00C10 for more details) + 240*2, 400); GPU_DepthMap(-1.0f, 0.0f); //Be careful, standard OpenGL clipping is [-1;1], but it is [-1;0] on the pica200 @@ -183,11 +194,11 @@ void gpuUIEndFrame() //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} - }; + { + {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; @@ -222,7 +233,7 @@ int main(int argc, char** argv) (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])); @@ -237,7 +248,7 @@ int main(int argc, char** argv) aptExit(); srvExit(); - return 0; + return 0; }