├── CMakeLists.txt ├── include ├── camera.h └── math_utils.h ├── shader ├── clear_f.cg ├── clear_v.cg ├── color_f.cg ├── color_v.cg ├── cube_f.cg ├── cube_v.cg ├── disable_color_buffer_f.cg └── disable_color_buffer_v.cg └── source ├── camera.c ├── main.c └── math_utils.c /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(gxmfun) 12 | 13 | include("${VITASDK}/share/vita.cmake" REQUIRED) 14 | 15 | set(VITA_APP_NAME "GXM Fun") 16 | set(VITA_TITLEID "GXMFUN000") 17 | set(VITA_VERSION "01.00") 18 | 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 21 | set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d PARENTAL_LEVEL=1") 22 | 23 | include_directories( 24 | include 25 | ) 26 | 27 | link_directories( 28 | ${CMAKE_BINARY_DIR} 29 | ) 30 | 31 | set(SOURCES 32 | source/main.c 33 | source/camera.c 34 | source/math_utils.c 35 | ) 36 | 37 | set(VERTEX_SHADERS 38 | shader/clear_v.cg 39 | shader/color_v.cg 40 | shader/cube_v.cg 41 | shader/disable_color_buffer_v.cg 42 | ) 43 | 44 | set(FRAGMENT_SHADERS 45 | shader/clear_f.cg 46 | shader/color_f.cg 47 | shader/cube_f.cg 48 | shader/disable_color_buffer_f.cg 49 | ) 50 | 51 | foreach(shader ${VERTEX_SHADERS}) 52 | get_filename_component(shader_we ${shader} NAME_WE) 53 | add_custom_command(OUTPUT "${shader_we}.gxp" 54 | COMMAND $ENV{PSP2CGC} -profile sce_vp_psp2 "${PROJECT_SOURCE_DIR}/${shader}" 55 | -o "${CMAKE_BINARY_DIR}/${shader_we}.gxp" 56 | DEPENDS ${shader} 57 | COMMENT "Compiling ${shader} to ${shader_we}.gxp" 58 | ) 59 | list(APPEND SHADER_GXPS "${shader_we}.gxp") 60 | endforeach() 61 | 62 | foreach(shader ${FRAGMENT_SHADERS}) 63 | get_filename_component(shader_we ${shader} NAME_WE) 64 | add_custom_command(OUTPUT "${shader_we}.gxp" 65 | COMMAND $ENV{PSP2CGC} -profile sce_fp_psp2 "${PROJECT_SOURCE_DIR}/${shader}" 66 | -o "${CMAKE_BINARY_DIR}/${shader_we}.gxp" 67 | DEPENDS ${shader} 68 | COMMENT "Compiling ${shader} to ${shader_we}.gxp" 69 | ) 70 | list(APPEND SHADER_GXPS "${shader_we}.gxp") 71 | endforeach() 72 | 73 | foreach(gxp ${SHADER_GXPS}) 74 | get_filename_component(gxp_we ${gxp} NAME_WE) 75 | add_custom_command(OUTPUT "${gxp_we}_gxp.o" 76 | COMMAND arm-vita-eabi-objcopy --input binary --output elf32-littlearm 77 | --binary-architecture arm "${gxp}" 78 | "${CMAKE_BINARY_DIR}/${gxp_we}_gxp.o" 79 | WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" 80 | DEPENDS ${gxp} 81 | COMMENT "Objcopying ${gxp} to ${gxp_we}_gxp.o" 82 | ) 83 | list(APPEND SHADER_OBJECTS "${gxp_we}_gxp.o") 84 | endforeach() 85 | 86 | add_executable(${PROJECT_NAME} 87 | ${SOURCES} 88 | ${SHADER_OBJECTS} 89 | ) 90 | 91 | target_link_libraries(${PROJECT_NAME} 92 | -lm 93 | SceDisplay_stub 94 | SceGxm_stub 95 | SceCtrl_stub 96 | SceSysmodule_stub 97 | ) 98 | 99 | vita_create_self(${PROJECT_NAME}.self ${PROJECT_NAME}) 100 | 101 | vita_create_vpk(${PROJECT_NAME}.vpk ${VITA_TITLEID} ${PROJECT_NAME}.self 102 | VERSION ${VITA_VERSION} 103 | NAME ${VITA_APP_NAME} 104 | ) 105 | 106 | add_custom_target(vpksend 107 | COMMAND curl -T ${PROJECT_NAME}.vpk ftp://$(PSVITAIP):1337/ux0:/ 108 | DEPENDS ${PROJECT_NAME}.vpk 109 | ) 110 | 111 | add_custom_target(send 112 | COMMAND curl -T ${PROJECT_NAME}.self ftp://$(PSVITAIP):1337/ux0:/app/${TITLE_ID}/eboot.bin 113 | DEPENDS ${PROJECT_NAME}.self 114 | ) 115 | -------------------------------------------------------------------------------- /include/camera.h: -------------------------------------------------------------------------------- 1 | #ifndef CAMERA_H 2 | #define CAMERA_H 3 | 4 | #include "math_utils.h" 5 | 6 | struct camera { 7 | vector3f position; 8 | vector3f rotation; 9 | matrix4x4 view_matrix; 10 | }; 11 | 12 | void camera_init_zero(struct camera *camera); 13 | void camera_init(struct camera *camera, const vector3f *pos, const vector3f *rot); 14 | void camera_update_view_matrix(struct camera *camera); 15 | void camera_get_look_vector(const struct camera *camera, vector3f *look); 16 | void camera_get_right_vector(const struct camera *camera, vector3f *right); 17 | void camera_get_up_vector(const struct camera *camera, vector3f *up); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /include/math_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_UTILS_H 2 | #define MATH_UTILS_H 3 | 4 | #include 5 | 6 | #define DEG_TO_RAD(x) ((x) * M_PI / 180.0) 7 | #define RAD_TO_RAD(x) ((x) * 180.0 / M_PI) 8 | 9 | typedef struct { 10 | float x, y; 11 | } vector2f; 12 | 13 | typedef struct { 14 | union { float x; float r; }; 15 | union { float y; float g; }; 16 | union { float z; float b; }; 17 | } vector3f; 18 | 19 | typedef struct { 20 | union { float x; float r; }; 21 | union { float y; float g; }; 22 | union { float z; float b; }; 23 | union { float w; float a; }; 24 | } vector4f; 25 | 26 | typedef float matrix3x3[3][3]; 27 | typedef float matrix4x4[4][4]; 28 | 29 | void vector3f_init(vector3f *v, float x, float y, float z); 30 | void vector3f_copy(vector3f *dst, const vector3f *src); 31 | float vector3f_length(const vector3f *v); 32 | void vector3f_add(vector3f *v1, const vector3f *v2); 33 | void vector3f_scalar_mult(vector3f *v, float a); 34 | void vector3f_add_mult(vector3f *v, const vector3f *u, float a); 35 | void vector3f_opposite(vector3f *v1, const vector3f *v0); 36 | float vector3f_dot_product(const vector3f *v1, const vector3f *v2); 37 | void vector3f_cross_product(vector3f *w, const vector3f *u, const vector3f *v); 38 | void vector3f_matrix4x4_mult(vector3f *u, const matrix4x4 m, const vector3f *v, float w); 39 | 40 | void vector4f_init(vector4f *v, float x, float y, float z, float w); 41 | void vector4f_scalar_mult_dest(vector4f *u, const vector4f *v, float a); 42 | float vector4f_dot_product(const vector4f *v1, const vector4f *v2); 43 | void vector4f_matrix4x4_mult(vector4f *u, const matrix4x4 m, const vector4f *v); 44 | 45 | void matrix3x3_identity(matrix3x3 m); 46 | void matrix3x3_from_matrix4x4(matrix3x3 dst, const matrix4x4 src); 47 | 48 | void matrix4x4_identity(matrix4x4 m); 49 | void matrix4x4_copy(matrix4x4 dst, const matrix4x4 src); 50 | 51 | void matrix4x4_multiply(matrix4x4 dst, const matrix4x4 src1, const matrix4x4 src2); 52 | 53 | void matrix4x4_init_rotation_x(matrix4x4 m, float rad); 54 | void matrix4x4_init_rotation_y(matrix4x4 m, float rad); 55 | void matrix4x4_init_rotation_z(matrix4x4 m, float rad); 56 | 57 | void matrix4x4_rotate_x(matrix4x4 m, float rad); 58 | void matrix4x4_rotate_y(matrix4x4 m, float rad); 59 | void matrix4x4_rotate_z(matrix4x4 m, float rad); 60 | 61 | void matrix4x4_init_translation(matrix4x4 m, float x, float y, float z); 62 | void matrix4x4_init_translation_vector3f(matrix4x4 m, const vector3f *v); 63 | void matrix4x4_translate(matrix4x4 m, float x, float y, float z); 64 | 65 | void matrix4x4_init_scaling(matrix4x4 m, float scale_x, float scale_y, float scale_z); 66 | void matrix4x4_scale(matrix4x4 m, float scale_x, float scale_y, float scale_z); 67 | void matrix4x4_reflect_origin(matrix4x4 m); 68 | 69 | void matrix4x4_transpose(matrix4x4 out, const matrix4x4 m); 70 | int matrix4x4_invert(matrix4x4 out, const matrix4x4 m); 71 | 72 | void matrix4x4_get_x_axis(const matrix4x4 m, vector3f *x_axis); 73 | void matrix4x4_get_y_axis(const matrix4x4 m, vector3f *y_axis); 74 | void matrix4x4_get_z_axis(const matrix4x4 m, vector3f *z_axis); 75 | 76 | void matrix4x4_init_orthographic(matrix4x4 m, float left, float right, float bottom, float top, float near, float far); 77 | void matrix4x4_init_frustum(matrix4x4 m, float left, float right, float bottom, float top, float near, float far); 78 | void matrix4x4_init_perspective(matrix4x4 m, float fov, float aspect, float near, float far); 79 | 80 | /* Graphics related */ 81 | 82 | void matrix3x3_normal_matrix(matrix3x3 out, const matrix4x4 m); 83 | void matrix4x4_build_model_matrix(matrix4x4 m, const vector3f *translation, 84 | const vector3f *rotation); 85 | void matrix4x4_oblique_near_plane(matrix4x4 projection, const vector4f *clip_plane); 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /shader/clear_f.cg: -------------------------------------------------------------------------------- 1 | float4 main(uniform float4 u_clear_color) : COLOR 2 | { 3 | return u_clear_color; 4 | } 5 | -------------------------------------------------------------------------------- /shader/clear_v.cg: -------------------------------------------------------------------------------- 1 | float4 main(float2 position) : POSITION 2 | { 3 | return float4(position, 1.f, 1.f); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /shader/color_f.cg: -------------------------------------------------------------------------------- 1 | float4 main(float4 color : COLOR) : COLOR 2 | { 3 | return color; 4 | } 5 | -------------------------------------------------------------------------------- /shader/color_v.cg: -------------------------------------------------------------------------------- 1 | void main( 2 | float3 position, 3 | float4 color, 4 | uniform float4x4 u_mvp_matrix, 5 | out float4 out_position: POSITION, 6 | out float4 out_color: COLOR) 7 | { 8 | out_position = mul(u_mvp_matrix, float4(position.x, position.y, 0.5f, 1.0f)); 9 | out_color = color; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /shader/cube_f.cg: -------------------------------------------------------------------------------- 1 | struct phong_material { 2 | float3 ambient; 3 | float3 diffuse; 4 | float3 specular; 5 | float shininess; 6 | }; 7 | 8 | struct light { 9 | float3 position; 10 | float3 color; 11 | }; 12 | 13 | uniform float4x4 u_modelview_matrix; 14 | uniform float3x3 u_normal_matrix; 15 | uniform phong_material u_material; 16 | uniform light u_light; 17 | 18 | float3 phong_lighting(float3 normal, float3 L, float3 position) 19 | { 20 | /* Ambient */ 21 | float3 ambient = u_material.ambient; 22 | 23 | /* Diffuse */ 24 | float3 diffuse = max(0.0f, dot(L, normal)) * u_material.diffuse; 25 | 26 | /* Specular */ 27 | float3 R = reflect(-L, normal); 28 | float3 V = normalize(-position); 29 | float specular_component = pow(max(0.0f, dot(R, V)), u_material.shininess); 30 | float3 specular = specular_component * u_material.specular; 31 | 32 | return (ambient + diffuse + specular) * u_light.color; 33 | } 34 | 35 | void main( 36 | float3 position : TEXCOORD0, 37 | float3 normal : TEXCOORD1, 38 | float4 color : COLOR, 39 | out float4 out_color : COLOR) 40 | { 41 | float3 position_eyespace = mul(u_modelview_matrix, float4(position, 1.0f)).xyz; 42 | float3 L = normalize(u_light.position - position_eyespace); 43 | float3 normal_eyespace = normalize(mul(u_normal_matrix, normal)); 44 | 45 | out_color = float4(phong_lighting(normal_eyespace, L, position_eyespace), 1.0f) * color; 46 | } 47 | -------------------------------------------------------------------------------- /shader/cube_v.cg: -------------------------------------------------------------------------------- 1 | float4 main( 2 | float3 position : POSITION, 3 | float3 normal : NORMAL, 4 | float4 color : COLOR, 5 | uniform float4x4 u_mvp_matrix, 6 | out float3 out_position: TEXCOORD0, 7 | out float3 out_normal: TEXCOORD1, 8 | out float4 out_color: COLOR) : POSITION 9 | { 10 | out_position = position; 11 | out_normal = normal; 12 | out_color = color; 13 | 14 | return mul(u_mvp_matrix, float4(position, 1.0f)); 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /shader/disable_color_buffer_f.cg: -------------------------------------------------------------------------------- 1 | float4 main() 2 | { 3 | return 0.0f; 4 | } 5 | -------------------------------------------------------------------------------- /shader/disable_color_buffer_v.cg: -------------------------------------------------------------------------------- 1 | float4 main( 2 | float3 position : POSITION, 3 | uniform float4x4 u_mvp_matrix) : POSITION 4 | { 5 | 6 | return mul(u_mvp_matrix, float4(position, 1.0f)); 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /source/camera.c: -------------------------------------------------------------------------------- 1 | #include "camera.h" 2 | 3 | void camera_init_zero(struct camera *camera) 4 | { 5 | vector3f_init(&camera->position, 0.0f, 0.0f, 0.0f); 6 | vector3f_init(&camera->rotation, 0.0f, 0.0f, 0.0f); 7 | matrix4x4_identity(camera->view_matrix); 8 | } 9 | 10 | void camera_init(struct camera *camera, const vector3f *pos, const vector3f *rot) 11 | { 12 | vector3f_copy(&camera->position, pos); 13 | vector3f_copy(&camera->rotation, rot); 14 | camera_update_view_matrix(camera); 15 | } 16 | 17 | void camera_update_view_matrix(struct camera *camera) 18 | { 19 | vector3f opposite; 20 | matrix4x4 mtmp, morient, mtrans; 21 | matrix4x4 mx, my, mz; 22 | 23 | vector3f_opposite(&opposite, &camera->position); 24 | 25 | matrix4x4_init_translation_vector3f(mtrans, &opposite); 26 | matrix4x4_init_rotation_x(mx, -camera->rotation.x); 27 | matrix4x4_init_rotation_y(my, -camera->rotation.y); 28 | matrix4x4_init_rotation_z(mz, -camera->rotation.z); 29 | 30 | matrix4x4_multiply(mtmp, mx, my); 31 | matrix4x4_multiply(morient, mtmp, mz); 32 | matrix4x4_multiply(camera->view_matrix, morient, mtrans); 33 | } 34 | 35 | void camera_get_look_vector(const struct camera *camera, vector3f *look) 36 | { 37 | matrix4x4_get_z_axis(camera->view_matrix, look); 38 | } 39 | 40 | void camera_get_right_vector(const struct camera *camera, vector3f *right) 41 | { 42 | matrix4x4_get_x_axis(camera->view_matrix, right); 43 | } 44 | 45 | void camera_get_up_vector(const struct camera *camera, vector3f *up) 46 | { 47 | matrix4x4_get_y_axis(camera->view_matrix, up); 48 | } 49 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "math_utils.h" 9 | #include "camera.h" 10 | 11 | #define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) 12 | #define abs(x) (((x) < 0) ? -(x) : (x)) 13 | 14 | #define ANALOG_THRESHOLD 20 15 | 16 | #define DISPLAY_WIDTH 960 17 | #define DISPLAY_HEIGHT 544 18 | #define DISPLAY_STRIDE 1024 19 | #define DISPLAY_BUFFER_COUNT 2 20 | #define DISPLAY_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8 21 | #define DISPLAY_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8 22 | #define MAX_PENDING_SWAPS (DISPLAY_BUFFER_COUNT - 1) 23 | 24 | struct clear_vertex { 25 | vector2f position; 26 | }; 27 | 28 | struct position_vertex { 29 | vector3f position; 30 | }; 31 | 32 | struct color_vertex { 33 | vector3f position; 34 | vector4f color; 35 | }; 36 | 37 | struct mesh_vertex { 38 | vector3f position; 39 | vector3f normal; 40 | vector4f color; 41 | }; 42 | 43 | struct phong_material { 44 | vector3f ambient; 45 | vector3f diffuse; 46 | vector3f specular; 47 | float shininess; 48 | }; 49 | 50 | struct light { 51 | vector3f position; 52 | vector3f color; 53 | }; 54 | 55 | struct portal { 56 | float width; 57 | float height; 58 | struct { 59 | matrix4x4 model_matrix; 60 | } end1, end2; 61 | }; 62 | 63 | 64 | struct scene_state { 65 | /* Portal's second end parameters */ 66 | vector3f portal_end2_translation; 67 | vector3f portal_end2_rotation; 68 | 69 | /* Light parameters */ 70 | float light_distance; 71 | float light_x_rot; 72 | float light_y_rot; 73 | 74 | struct light light; 75 | 76 | struct portal portal; 77 | }; 78 | 79 | struct phong_material_gxm_params { 80 | const SceGxmProgramParameter *ambient; 81 | const SceGxmProgramParameter *diffuse; 82 | const SceGxmProgramParameter *specular; 83 | const SceGxmProgramParameter *shininess; 84 | }; 85 | 86 | struct light_gxm_params { 87 | const SceGxmProgramParameter *position; 88 | const SceGxmProgramParameter *color; 89 | }; 90 | 91 | struct display_queue_callback_data { 92 | void *addr; 93 | }; 94 | 95 | extern unsigned char _binary_disable_color_buffer_v_gxp_start; 96 | extern unsigned char _binary_disable_color_buffer_f_gxp_start; 97 | extern unsigned char _binary_clear_v_gxp_start; 98 | extern unsigned char _binary_clear_f_gxp_start; 99 | extern unsigned char _binary_cube_v_gxp_start; 100 | extern unsigned char _binary_cube_f_gxp_start; 101 | 102 | static const SceGxmProgram *const gxm_program_disable_color_buffer_v = (SceGxmProgram *)&_binary_disable_color_buffer_v_gxp_start; 103 | static const SceGxmProgram *const gxm_program_disable_color_buffer_f = (SceGxmProgram *)&_binary_disable_color_buffer_f_gxp_start; 104 | static const SceGxmProgram *const gxm_program_clear_v = (SceGxmProgram *)&_binary_clear_v_gxp_start; 105 | static const SceGxmProgram *const gxm_program_clear_f = (SceGxmProgram *)&_binary_clear_f_gxp_start; 106 | static const SceGxmProgram *const gxm_program_cube_v = (SceGxmProgram *)&_binary_cube_v_gxp_start; 107 | static const SceGxmProgram *const gxm_program_cube_f = (SceGxmProgram *)&_binary_cube_f_gxp_start; 108 | 109 | static SceGxmContext *gxm_context; 110 | static SceUID vdm_ring_buffer_uid; 111 | static void *vdm_ring_buffer_addr; 112 | static SceUID vertex_ring_buffer_uid; 113 | static void *vertex_ring_buffer_addr; 114 | static SceUID fragment_ring_buffer_uid; 115 | static void *fragment_ring_buffer_addr; 116 | static SceUID fragment_usse_ring_buffer_uid; 117 | static void *fragment_usse_ring_buffer_addr; 118 | static SceGxmRenderTarget *gxm_render_target; 119 | static SceGxmColorSurface gxm_color_surfaces[DISPLAY_BUFFER_COUNT]; 120 | static SceUID gxm_color_surfaces_uid[DISPLAY_BUFFER_COUNT]; 121 | static void *gxm_color_surfaces_addr[DISPLAY_BUFFER_COUNT]; 122 | static SceGxmSyncObject *gxm_sync_objects[DISPLAY_BUFFER_COUNT]; 123 | static unsigned int gxm_front_buffer_index; 124 | static unsigned int gxm_back_buffer_index; 125 | static SceUID gxm_depth_stencil_surface_uid; 126 | static void *gxm_depth_stencil_surface_addr; 127 | static SceGxmDepthStencilSurface gxm_depth_stencil_surface; 128 | static SceGxmShaderPatcher *gxm_shader_patcher; 129 | static SceUID gxm_shader_patcher_buffer_uid; 130 | static void *gxm_shader_patcher_buffer_addr; 131 | static SceUID gxm_shader_patcher_vertex_usse_uid; 132 | static void *gxm_shader_patcher_vertex_usse_addr; 133 | static SceUID gxm_shader_patcher_fragment_usse_uid; 134 | static void *gxm_shader_patcher_fragment_usse_addr; 135 | 136 | static SceGxmShaderPatcherId gxm_disable_color_buffer_vertex_program_id; 137 | static SceGxmShaderPatcherId gxm_disable_color_buffer_fragment_program_id; 138 | static const SceGxmProgramParameter *gxm_disable_color_buffer_vertex_program_position_param; 139 | static const SceGxmProgramParameter *gxm_disable_color_buffer_vertex_program_u_mvp_matrix_param; 140 | static SceGxmVertexProgram *gxm_disable_color_buffer_vertex_program_patched; 141 | static SceGxmFragmentProgram *gxm_disable_color_buffer_fragment_program_patched; 142 | 143 | static SceGxmShaderPatcherId gxm_clear_vertex_program_id; 144 | static SceGxmShaderPatcherId gxm_clear_fragment_program_id; 145 | static const SceGxmProgramParameter *gxm_clear_vertex_program_position_param; 146 | static const SceGxmProgramParameter *gxm_clear_fragment_program_u_clear_color_param; 147 | static SceGxmVertexProgram *gxm_clear_vertex_program_patched; 148 | static SceGxmFragmentProgram *gxm_clear_fragment_program_patched; 149 | 150 | static SceGxmShaderPatcherId gxm_cube_vertex_program_id; 151 | static SceGxmShaderPatcherId gxm_cube_fragment_program_id; 152 | static const SceGxmProgramParameter *gxm_cube_vertex_program_position_param; 153 | static const SceGxmProgramParameter *gxm_cube_vertex_program_normal_param; 154 | static const SceGxmProgramParameter *gxm_cube_vertex_program_color_param; 155 | static const SceGxmProgramParameter *gxm_cube_vertex_program_u_mvp_matrix_param; 156 | static const SceGxmProgramParameter *gxm_cube_fragment_program_u_modelview_matrix_param; 157 | static const SceGxmProgramParameter *gxm_cube_fragment_program_u_normal_matrix_param; 158 | static struct phong_material_gxm_params gxm_cube_fragment_program_phong_material_params; 159 | static struct light_gxm_params gxm_cube_fragment_program_light_params; 160 | static SceGxmVertexProgram *gxm_cube_vertex_program_patched; 161 | static SceGxmFragmentProgram *gxm_cube_fragment_program_patched; 162 | 163 | static struct mesh_vertex *cube_mesh_data; 164 | static unsigned short *cube_indices_data; 165 | static struct mesh_vertex *floor_mesh_data; 166 | static unsigned short *floor_indices_data; 167 | static struct mesh_vertex *portal_frame_mesh_data; 168 | static unsigned short *portal_frame_indices_data; 169 | 170 | static void set_vertex_default_uniform_data(const SceGxmProgramParameter *param, 171 | unsigned int component_count, const void *data); 172 | static void set_fragment_default_uniform_data(const SceGxmProgramParameter *param, 173 | unsigned int component_count, const void *data); 174 | static void set_cube_fragment_material_uniform_params(const struct phong_material *material, 175 | const struct phong_material_gxm_params *params); 176 | static void set_cube_matrices_uniform_params(matrix4x4 mvp_matrix, 177 | matrix4x4 modelview_matrix, matrix3x3 normal_matrix); 178 | static void set_cube_fragment_light_uniform_params(const struct light *light, 179 | const struct light_gxm_params *params); 180 | 181 | static void update_camera(struct camera *camera, SceCtrlData *pad); 182 | static void draw_scene(const struct scene_state *state, matrix4x4 projection_matrix, matrix4x4 view_matrix); 183 | static void update_scene(struct scene_state *state, const struct camera *camera, SceCtrlData *pad); 184 | 185 | static void draw_cube(const struct scene_state *state, const matrix4x4 projection_matrix, 186 | const matrix4x4 view_matrix, const matrix4x4 model_matrix, const struct phong_material *material); 187 | 188 | static void *gpu_alloc_map(SceKernelMemBlockType type, SceGxmMemoryAttribFlags gpu_attrib, size_t size, SceUID *uid); 189 | static void gpu_unmap_free(SceUID uid); 190 | static void *gpu_vertex_usse_alloc_map(size_t size, SceUID *uid, unsigned int *usse_offset); 191 | static void gpu_vertex_usse_unmap_free(SceUID uid); 192 | static void *gpu_fragment_usse_alloc_map(size_t size, SceUID *uid, unsigned int *usse_offset); 193 | static void gpu_fragment_usse_unmap_free(SceUID uid); 194 | static void *shader_patcher_host_alloc_cb(void *user_data, unsigned int size); 195 | static void shader_patcher_host_free_cb(void *user_data, void *mem); 196 | static void display_queue_callback(const void *callbackData); 197 | 198 | int main(int argc, char *argv[]) 199 | { 200 | int i; 201 | 202 | sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG); 203 | 204 | SceGxmInitializeParams gxm_init_params; 205 | memset(&gxm_init_params, 0, sizeof(gxm_init_params)); 206 | gxm_init_params.flags = 0; 207 | gxm_init_params.displayQueueMaxPendingCount = MAX_PENDING_SWAPS; 208 | gxm_init_params.displayQueueCallback = display_queue_callback; 209 | gxm_init_params.displayQueueCallbackDataSize = sizeof(struct display_queue_callback_data); 210 | gxm_init_params.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE; 211 | 212 | sceGxmInitialize(&gxm_init_params); 213 | 214 | vdm_ring_buffer_addr = gpu_alloc_map(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 215 | SCE_GXM_MEMORY_ATTRIB_READ, SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE, 216 | &vdm_ring_buffer_uid); 217 | 218 | vertex_ring_buffer_addr = gpu_alloc_map(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 219 | SCE_GXM_MEMORY_ATTRIB_READ, SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE, 220 | &vertex_ring_buffer_uid); 221 | 222 | fragment_ring_buffer_addr = gpu_alloc_map(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 223 | SCE_GXM_MEMORY_ATTRIB_READ, SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE, 224 | &fragment_ring_buffer_uid); 225 | 226 | unsigned int fragment_usse_offset; 227 | fragment_usse_ring_buffer_addr = gpu_fragment_usse_alloc_map( 228 | SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE, 229 | &fragment_usse_ring_buffer_uid, &fragment_usse_offset); 230 | 231 | SceGxmContextParams gxm_context_params; 232 | memset(&gxm_context_params, 0, sizeof(gxm_context_params)); 233 | gxm_context_params.hostMem = malloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE); 234 | gxm_context_params.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE; 235 | gxm_context_params.vdmRingBufferMem = vdm_ring_buffer_addr; 236 | gxm_context_params.vdmRingBufferMemSize = SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE; 237 | gxm_context_params.vertexRingBufferMem = vertex_ring_buffer_addr; 238 | gxm_context_params.vertexRingBufferMemSize = SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE; 239 | gxm_context_params.fragmentRingBufferMem = fragment_ring_buffer_addr; 240 | gxm_context_params.fragmentRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE; 241 | gxm_context_params.fragmentUsseRingBufferMem = fragment_usse_ring_buffer_addr; 242 | gxm_context_params.fragmentUsseRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE; 243 | gxm_context_params.fragmentUsseRingBufferOffset = fragment_usse_offset; 244 | 245 | sceGxmCreateContext(&gxm_context_params, &gxm_context); 246 | 247 | SceGxmRenderTargetParams render_target_params; 248 | memset(&render_target_params, 0, sizeof(render_target_params)); 249 | render_target_params.flags = 0; 250 | render_target_params.width = DISPLAY_WIDTH; 251 | render_target_params.height = DISPLAY_HEIGHT; 252 | render_target_params.scenesPerFrame = 1; 253 | render_target_params.multisampleMode = SCE_GXM_MULTISAMPLE_NONE; 254 | render_target_params.multisampleLocations = 0; 255 | render_target_params.driverMemBlock = -1; 256 | 257 | sceGxmCreateRenderTarget(&render_target_params, &gxm_render_target); 258 | 259 | for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) { 260 | gxm_color_surfaces_addr[i] = gpu_alloc_map(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 261 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, 262 | ALIGN(4 * DISPLAY_STRIDE * DISPLAY_HEIGHT, 1 * 1024 * 1024), 263 | &gxm_color_surfaces_uid[i]); 264 | 265 | memset(gxm_color_surfaces_addr[i], 0, DISPLAY_STRIDE * DISPLAY_HEIGHT); 266 | 267 | sceGxmColorSurfaceInit(&gxm_color_surfaces[i], 268 | DISPLAY_COLOR_FORMAT, 269 | SCE_GXM_COLOR_SURFACE_LINEAR, 270 | SCE_GXM_COLOR_SURFACE_SCALE_NONE, 271 | SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, 272 | DISPLAY_WIDTH, 273 | DISPLAY_HEIGHT, 274 | DISPLAY_STRIDE, 275 | gxm_color_surfaces_addr[i]); 276 | 277 | sceGxmSyncObjectCreate(&gxm_sync_objects[i]); 278 | } 279 | 280 | unsigned int depth_stencil_width = ALIGN(DISPLAY_WIDTH, SCE_GXM_TILE_SIZEX); 281 | unsigned int depth_stencil_height = ALIGN(DISPLAY_HEIGHT, SCE_GXM_TILE_SIZEY); 282 | unsigned int depth_stencil_samples = depth_stencil_width * depth_stencil_height; 283 | 284 | gxm_depth_stencil_surface_addr = gpu_alloc_map(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 285 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE, 286 | 4 * depth_stencil_samples, &gxm_depth_stencil_surface_uid); 287 | 288 | sceGxmDepthStencilSurfaceInit(&gxm_depth_stencil_surface, 289 | SCE_GXM_DEPTH_STENCIL_FORMAT_S8D24, 290 | SCE_GXM_DEPTH_STENCIL_SURFACE_TILED, 291 | depth_stencil_width, 292 | gxm_depth_stencil_surface_addr, 293 | NULL); 294 | 295 | static const unsigned int shader_patcher_buffer_size = 64 * 1024; 296 | static const unsigned int shader_patcher_vertex_usse_size = 64 * 1024; 297 | static const unsigned int shader_patcher_fragment_usse_size = 64 * 1024; 298 | 299 | gxm_shader_patcher_buffer_addr = gpu_alloc_map(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, 300 | SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_READ, 301 | shader_patcher_buffer_size, &gxm_shader_patcher_buffer_uid); 302 | 303 | unsigned int shader_patcher_vertex_usse_offset; 304 | gxm_shader_patcher_vertex_usse_addr = gpu_vertex_usse_alloc_map( 305 | shader_patcher_vertex_usse_size, &gxm_shader_patcher_vertex_usse_uid, 306 | &shader_patcher_vertex_usse_offset); 307 | 308 | unsigned int shader_patcher_fragment_usse_offset; 309 | gxm_shader_patcher_fragment_usse_addr = gpu_fragment_usse_alloc_map( 310 | shader_patcher_fragment_usse_size, &gxm_shader_patcher_fragment_usse_uid, 311 | &shader_patcher_fragment_usse_offset); 312 | 313 | SceGxmShaderPatcherParams shader_patcher_params; 314 | memset(&shader_patcher_params, 0, sizeof(shader_patcher_params)); 315 | shader_patcher_params.userData = NULL; 316 | shader_patcher_params.hostAllocCallback = shader_patcher_host_alloc_cb; 317 | shader_patcher_params.hostFreeCallback = shader_patcher_host_free_cb; 318 | shader_patcher_params.bufferAllocCallback = NULL; 319 | shader_patcher_params.bufferFreeCallback = NULL; 320 | shader_patcher_params.bufferMem = gxm_shader_patcher_buffer_addr; 321 | shader_patcher_params.bufferMemSize = shader_patcher_buffer_size; 322 | shader_patcher_params.vertexUsseAllocCallback = NULL; 323 | shader_patcher_params.vertexUsseFreeCallback = NULL; 324 | shader_patcher_params.vertexUsseMem = gxm_shader_patcher_vertex_usse_addr; 325 | shader_patcher_params.vertexUsseMemSize = shader_patcher_vertex_usse_size; 326 | shader_patcher_params.vertexUsseOffset = shader_patcher_vertex_usse_offset; 327 | shader_patcher_params.fragmentUsseAllocCallback = NULL; 328 | shader_patcher_params.fragmentUsseFreeCallback = NULL; 329 | shader_patcher_params.fragmentUsseMem = gxm_shader_patcher_fragment_usse_addr; 330 | shader_patcher_params.fragmentUsseMemSize = shader_patcher_fragment_usse_size; 331 | shader_patcher_params.fragmentUsseOffset = shader_patcher_fragment_usse_offset; 332 | 333 | sceGxmShaderPatcherCreate(&shader_patcher_params, &gxm_shader_patcher); 334 | 335 | sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_disable_color_buffer_v, 336 | &gxm_disable_color_buffer_vertex_program_id); 337 | sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_disable_color_buffer_f, 338 | &gxm_disable_color_buffer_fragment_program_id); 339 | 340 | const SceGxmProgram *disable_color_buffer_vertex_program = 341 | sceGxmShaderPatcherGetProgramFromId(gxm_disable_color_buffer_vertex_program_id); 342 | 343 | gxm_disable_color_buffer_vertex_program_position_param = sceGxmProgramFindParameterByName( 344 | disable_color_buffer_vertex_program, "position"); 345 | 346 | gxm_disable_color_buffer_vertex_program_u_mvp_matrix_param = sceGxmProgramFindParameterByName( 347 | disable_color_buffer_vertex_program, "u_mvp_matrix"); 348 | 349 | SceGxmVertexAttribute disable_color_buffer_attributes; 350 | SceGxmVertexStream disable_color_buffer_stream; 351 | disable_color_buffer_attributes.streamIndex = 0; 352 | disable_color_buffer_attributes.offset = 0; 353 | disable_color_buffer_attributes.format = SCE_GXM_ATTRIBUTE_FORMAT_F32; 354 | disable_color_buffer_attributes.componentCount = 3; 355 | disable_color_buffer_attributes.regIndex = sceGxmProgramParameterGetResourceIndex( 356 | gxm_disable_color_buffer_vertex_program_position_param); 357 | disable_color_buffer_stream.stride = sizeof(struct position_vertex); 358 | disable_color_buffer_stream.indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; 359 | 360 | sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, 361 | gxm_disable_color_buffer_vertex_program_id, &disable_color_buffer_attributes, 362 | 1, &disable_color_buffer_stream, 1, &gxm_disable_color_buffer_vertex_program_patched); 363 | 364 | SceGxmBlendInfo disable_color_buffer_blend_info; 365 | memset(&disable_color_buffer_blend_info, 0, sizeof(disable_color_buffer_blend_info)); 366 | disable_color_buffer_blend_info.colorMask = SCE_GXM_COLOR_MASK_NONE; 367 | disable_color_buffer_blend_info.colorFunc = SCE_GXM_BLEND_FUNC_NONE; 368 | disable_color_buffer_blend_info.alphaFunc = SCE_GXM_BLEND_FUNC_NONE; 369 | disable_color_buffer_blend_info.colorSrc = SCE_GXM_BLEND_FACTOR_ZERO; 370 | disable_color_buffer_blend_info.colorDst = SCE_GXM_BLEND_FACTOR_ZERO; 371 | disable_color_buffer_blend_info.alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO; 372 | disable_color_buffer_blend_info.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO; 373 | 374 | sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, 375 | gxm_disable_color_buffer_fragment_program_id, 376 | SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, 377 | SCE_GXM_MULTISAMPLE_NONE, 378 | &disable_color_buffer_blend_info, 379 | disable_color_buffer_vertex_program, 380 | &gxm_disable_color_buffer_fragment_program_patched); 381 | 382 | sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_v, 383 | &gxm_clear_vertex_program_id); 384 | sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_f, 385 | &gxm_clear_fragment_program_id); 386 | 387 | const SceGxmProgram *clear_vertex_program = 388 | sceGxmShaderPatcherGetProgramFromId(gxm_clear_vertex_program_id); 389 | const SceGxmProgram *clear_fragment_program = 390 | sceGxmShaderPatcherGetProgramFromId(gxm_clear_fragment_program_id); 391 | 392 | gxm_clear_vertex_program_position_param = sceGxmProgramFindParameterByName( 393 | clear_vertex_program, "position"); 394 | 395 | gxm_clear_fragment_program_u_clear_color_param = sceGxmProgramFindParameterByName( 396 | clear_fragment_program, "u_clear_color"); 397 | 398 | SceGxmVertexAttribute clear_vertex_attribute; 399 | SceGxmVertexStream clear_vertex_stream; 400 | clear_vertex_attribute.streamIndex = 0; 401 | clear_vertex_attribute.offset = 0; 402 | clear_vertex_attribute.format = SCE_GXM_ATTRIBUTE_FORMAT_F32; 403 | clear_vertex_attribute.componentCount = 2; 404 | clear_vertex_attribute.regIndex = sceGxmProgramParameterGetResourceIndex( 405 | gxm_clear_vertex_program_position_param); 406 | clear_vertex_stream.stride = sizeof(struct clear_vertex); 407 | clear_vertex_stream.indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; 408 | 409 | sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, 410 | gxm_clear_vertex_program_id, &clear_vertex_attribute, 411 | 1, &clear_vertex_stream, 1, &gxm_clear_vertex_program_patched); 412 | 413 | sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, 414 | gxm_clear_fragment_program_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, 415 | SCE_GXM_MULTISAMPLE_NONE, NULL, clear_vertex_program, 416 | &gxm_clear_fragment_program_patched); 417 | 418 | SceUID clear_vertices_uid; 419 | struct clear_vertex *const clear_vertices_data = gpu_alloc_map( 420 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 421 | 4 * sizeof(struct clear_vertex), &clear_vertices_uid); 422 | 423 | SceUID clear_indices_uid; 424 | unsigned short *const clear_indices_data = gpu_alloc_map( 425 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 426 | 4 * sizeof(unsigned short), &clear_indices_uid); 427 | 428 | clear_vertices_data[0].position = (vector2f){-1.0f, -1.0f}; 429 | clear_vertices_data[1].position = (vector2f){ 1.0f, -1.0f}; 430 | clear_vertices_data[2].position = (vector2f){-1.0f, 1.0f}; 431 | clear_vertices_data[3].position = (vector2f){ 1.0f, 1.0f}; 432 | 433 | clear_indices_data[0] = 0; 434 | clear_indices_data[1] = 1; 435 | clear_indices_data[2] = 2; 436 | clear_indices_data[3] = 3; 437 | 438 | sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_cube_v, 439 | &gxm_cube_vertex_program_id); 440 | sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_cube_f, 441 | &gxm_cube_fragment_program_id); 442 | 443 | const SceGxmProgram *cube_vertex_program = 444 | sceGxmShaderPatcherGetProgramFromId(gxm_cube_vertex_program_id); 445 | const SceGxmProgram *cube_fragment_program = 446 | sceGxmShaderPatcherGetProgramFromId(gxm_cube_fragment_program_id); 447 | 448 | gxm_cube_vertex_program_position_param = sceGxmProgramFindParameterByName( 449 | cube_vertex_program, "position"); 450 | gxm_cube_vertex_program_normal_param = sceGxmProgramFindParameterByName( 451 | cube_vertex_program, "normal"); 452 | gxm_cube_vertex_program_color_param = sceGxmProgramFindParameterByName( 453 | cube_vertex_program, "color"); 454 | gxm_cube_vertex_program_u_mvp_matrix_param = sceGxmProgramFindParameterByName( 455 | cube_vertex_program, "u_mvp_matrix"); 456 | 457 | gxm_cube_fragment_program_u_modelview_matrix_param = sceGxmProgramFindParameterByName( 458 | cube_fragment_program, "u_modelview_matrix"); 459 | gxm_cube_fragment_program_u_normal_matrix_param = sceGxmProgramFindParameterByName( 460 | cube_fragment_program, "u_normal_matrix"); 461 | 462 | gxm_cube_fragment_program_phong_material_params.ambient = sceGxmProgramFindParameterByName( 463 | cube_fragment_program, "u_material.ambient"); 464 | gxm_cube_fragment_program_phong_material_params.diffuse = sceGxmProgramFindParameterByName( 465 | cube_fragment_program, "u_material.diffuse"); 466 | gxm_cube_fragment_program_phong_material_params.specular = sceGxmProgramFindParameterByName( 467 | cube_fragment_program, "u_material.specular"); 468 | gxm_cube_fragment_program_phong_material_params.shininess = sceGxmProgramFindParameterByName( 469 | cube_fragment_program, "u_material.shininess"); 470 | 471 | gxm_cube_fragment_program_light_params.position = sceGxmProgramFindParameterByName( 472 | cube_fragment_program, "u_light.position"); 473 | gxm_cube_fragment_program_light_params.color = sceGxmProgramFindParameterByName( 474 | cube_fragment_program, "u_light.color"); 475 | 476 | SceGxmVertexAttribute cube_vertex_attributes[3]; 477 | SceGxmVertexStream cube_vertex_stream; 478 | cube_vertex_attributes[0].streamIndex = 0; 479 | cube_vertex_attributes[0].offset = 0; 480 | cube_vertex_attributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; 481 | cube_vertex_attributes[0].componentCount = 3; 482 | cube_vertex_attributes[0].regIndex = sceGxmProgramParameterGetResourceIndex( 483 | gxm_cube_vertex_program_position_param); 484 | cube_vertex_attributes[1].streamIndex = 0; 485 | cube_vertex_attributes[1].offset = sizeof(vector3f); 486 | cube_vertex_attributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; 487 | cube_vertex_attributes[1].componentCount = 3; 488 | cube_vertex_attributes[1].regIndex = sceGxmProgramParameterGetResourceIndex( 489 | gxm_cube_vertex_program_normal_param); 490 | cube_vertex_attributes[2].streamIndex = 0; 491 | cube_vertex_attributes[2].offset = 2 * sizeof(vector3f); 492 | cube_vertex_attributes[2].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; 493 | cube_vertex_attributes[2].componentCount = 4; 494 | cube_vertex_attributes[2].regIndex = sceGxmProgramParameterGetResourceIndex( 495 | gxm_cube_vertex_program_color_param); 496 | cube_vertex_stream.stride = sizeof(struct mesh_vertex); 497 | cube_vertex_stream.indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; 498 | 499 | sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, 500 | gxm_cube_vertex_program_id, cube_vertex_attributes, 501 | 3, &cube_vertex_stream, 1, &gxm_cube_vertex_program_patched); 502 | 503 | sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, 504 | gxm_cube_fragment_program_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, 505 | SCE_GXM_MULTISAMPLE_NONE, NULL, cube_vertex_program, 506 | &gxm_cube_fragment_program_patched); 507 | 508 | SceUID cube_mesh_uid; 509 | cube_mesh_data = gpu_alloc_map( 510 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 511 | 36 * sizeof(struct mesh_vertex), &cube_mesh_uid); 512 | 513 | SceUID cube_indices_uid; 514 | cube_indices_data = gpu_alloc_map( 515 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 516 | 36 * sizeof(unsigned short), &cube_indices_uid); 517 | 518 | #define CUBE_SIZE 1.0f 519 | #define CUBE_HALF_SIZE (CUBE_SIZE / 2.0f) 520 | 521 | static const vector3f cube_vertices[] = { 522 | {.x = -CUBE_HALF_SIZE, .y = +CUBE_HALF_SIZE, .z = +CUBE_HALF_SIZE}, 523 | {.x = -CUBE_HALF_SIZE, .y = -CUBE_HALF_SIZE, .z = +CUBE_HALF_SIZE}, 524 | {.x = +CUBE_HALF_SIZE, .y = +CUBE_HALF_SIZE, .z = +CUBE_HALF_SIZE}, 525 | {.x = +CUBE_HALF_SIZE, .y = -CUBE_HALF_SIZE, .z = +CUBE_HALF_SIZE}, 526 | {.x = +CUBE_HALF_SIZE, .y = +CUBE_HALF_SIZE, .z = -CUBE_HALF_SIZE}, 527 | {.x = +CUBE_HALF_SIZE, .y = -CUBE_HALF_SIZE, .z = -CUBE_HALF_SIZE}, 528 | {.x = -CUBE_HALF_SIZE, .y = +CUBE_HALF_SIZE, .z = -CUBE_HALF_SIZE}, 529 | {.x = -CUBE_HALF_SIZE, .y = -CUBE_HALF_SIZE, .z = -CUBE_HALF_SIZE} 530 | }; 531 | 532 | static const vector3f cube_face_normals[] = { 533 | {.x = 0.0f, .y = 0.0f, .z = 1.0f}, /* Front */ 534 | {.x = 1.0f, .y = 0.0f, .z = 0.0f}, /* Right */ 535 | {.x = 0.0f, .y = 0.0f, .z = -1.0f}, /* Back */ 536 | {.x = -1.0f, .y = 0.0f, .z = 0.0f}, /* Left */ 537 | {.x = 0.0f, .y = 1.0f, .z = 0.0f}, /* Top */ 538 | {.x = 0.0f, .y = -1.0f, .z = 0.0f}, /* Bottom */ 539 | }; 540 | 541 | static const vector4f cube_colors[] = { 542 | {.r = 1.0f, .g = 0.0f, .b = 0.0f, .a = 1.0f}, 543 | {.r = 0.0f, .g = 1.0f, .b = 0.0f, .a = 1.0f}, 544 | {.r = 0.0f, .g = 0.0f, .b = 1.0f, .a = 1.0f}, 545 | {.r = 1.0f, .g = 1.0f, .b = 0.0f, .a = 1.0f}, 546 | {.r = 0.0f, .g = 1.0f, .b = 1.0f, .a = 1.0f}, 547 | {.r = 1.0f, .g = 0.0f, .b = 1.0f, .a = 1.0f}, 548 | }; 549 | 550 | cube_mesh_data[0] = (struct mesh_vertex){cube_vertices[0], cube_face_normals[0], cube_colors[0]}; 551 | cube_mesh_data[1] = (struct mesh_vertex){cube_vertices[1], cube_face_normals[0], cube_colors[0]}; 552 | cube_mesh_data[2] = (struct mesh_vertex){cube_vertices[2], cube_face_normals[0], cube_colors[0]}; 553 | cube_mesh_data[3] = (struct mesh_vertex){cube_vertices[2], cube_face_normals[0], cube_colors[0]}; 554 | cube_mesh_data[4] = (struct mesh_vertex){cube_vertices[1], cube_face_normals[0], cube_colors[0]}; 555 | cube_mesh_data[5] = (struct mesh_vertex){cube_vertices[3], cube_face_normals[0], cube_colors[0]}; 556 | 557 | cube_mesh_data[6] = (struct mesh_vertex){cube_vertices[2], cube_face_normals[1], cube_colors[1]}; 558 | cube_mesh_data[7] = (struct mesh_vertex){cube_vertices[3], cube_face_normals[1], cube_colors[1]}; 559 | cube_mesh_data[8] = (struct mesh_vertex){cube_vertices[4], cube_face_normals[1], cube_colors[1]}; 560 | cube_mesh_data[9] = (struct mesh_vertex){cube_vertices[4], cube_face_normals[1], cube_colors[1]}; 561 | cube_mesh_data[10] = (struct mesh_vertex){cube_vertices[3], cube_face_normals[1], cube_colors[1]}; 562 | cube_mesh_data[11] = (struct mesh_vertex){cube_vertices[5], cube_face_normals[1], cube_colors[1]}; 563 | 564 | cube_mesh_data[12] = (struct mesh_vertex){cube_vertices[4], cube_face_normals[2], cube_colors[2]}; 565 | cube_mesh_data[13] = (struct mesh_vertex){cube_vertices[5], cube_face_normals[2], cube_colors[2]}; 566 | cube_mesh_data[14] = (struct mesh_vertex){cube_vertices[6], cube_face_normals[2], cube_colors[2]}; 567 | cube_mesh_data[15] = (struct mesh_vertex){cube_vertices[6], cube_face_normals[2], cube_colors[2]}; 568 | cube_mesh_data[16] = (struct mesh_vertex){cube_vertices[5], cube_face_normals[2], cube_colors[2]}; 569 | cube_mesh_data[17] = (struct mesh_vertex){cube_vertices[7], cube_face_normals[2], cube_colors[2]}; 570 | 571 | cube_mesh_data[18] = (struct mesh_vertex){cube_vertices[6], cube_face_normals[3], cube_colors[3]}; 572 | cube_mesh_data[19] = (struct mesh_vertex){cube_vertices[7], cube_face_normals[3], cube_colors[3]}; 573 | cube_mesh_data[20] = (struct mesh_vertex){cube_vertices[0], cube_face_normals[3], cube_colors[3]}; 574 | cube_mesh_data[21] = (struct mesh_vertex){cube_vertices[0], cube_face_normals[3], cube_colors[3]}; 575 | cube_mesh_data[22] = (struct mesh_vertex){cube_vertices[7], cube_face_normals[3], cube_colors[3]}; 576 | cube_mesh_data[23] = (struct mesh_vertex){cube_vertices[1], cube_face_normals[3], cube_colors[3]}; 577 | 578 | cube_mesh_data[24] = (struct mesh_vertex){cube_vertices[6], cube_face_normals[4], cube_colors[4]}; 579 | cube_mesh_data[25] = (struct mesh_vertex){cube_vertices[0], cube_face_normals[4], cube_colors[4]}; 580 | cube_mesh_data[26] = (struct mesh_vertex){cube_vertices[4], cube_face_normals[4], cube_colors[4]}; 581 | cube_mesh_data[27] = (struct mesh_vertex){cube_vertices[4], cube_face_normals[4], cube_colors[4]}; 582 | cube_mesh_data[28] = (struct mesh_vertex){cube_vertices[0], cube_face_normals[4], cube_colors[4]}; 583 | cube_mesh_data[29] = (struct mesh_vertex){cube_vertices[2], cube_face_normals[4], cube_colors[4]}; 584 | 585 | cube_mesh_data[30] = (struct mesh_vertex){cube_vertices[1], cube_face_normals[5], cube_colors[5]}; 586 | cube_mesh_data[31] = (struct mesh_vertex){cube_vertices[7], cube_face_normals[5], cube_colors[5]}; 587 | cube_mesh_data[32] = (struct mesh_vertex){cube_vertices[3], cube_face_normals[5], cube_colors[5]}; 588 | cube_mesh_data[33] = (struct mesh_vertex){cube_vertices[3], cube_face_normals[5], cube_colors[5]}; 589 | cube_mesh_data[34] = (struct mesh_vertex){cube_vertices[7], cube_face_normals[5], cube_colors[5]}; 590 | cube_mesh_data[35] = (struct mesh_vertex){cube_vertices[5], cube_face_normals[5], cube_colors[5]}; 591 | 592 | for (i = 0; i < 36; i++) 593 | cube_indices_data[i] = i; 594 | 595 | SceUID floor_mesh_uid; 596 | floor_mesh_data = gpu_alloc_map( 597 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 598 | 4 * sizeof(struct mesh_vertex), &floor_mesh_uid); 599 | 600 | SceUID floor_indices_uid; 601 | floor_indices_data = gpu_alloc_map( 602 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 603 | 4 * sizeof(unsigned short), &floor_indices_uid); 604 | 605 | #define FLOOR_SIZE 20.0f 606 | #define FLOOR_HALF_SIZE (FLOOR_SIZE / 2.0f) 607 | 608 | static const vector3f floor_vertices[] = { 609 | {.x = -FLOOR_HALF_SIZE, .y = 0.0f, .z = -FLOOR_HALF_SIZE}, 610 | {.x = -FLOOR_HALF_SIZE, .y = 0.0f, .z = +FLOOR_HALF_SIZE}, 611 | {.x = +FLOOR_HALF_SIZE, .y = 0.0f, .z = -FLOOR_HALF_SIZE}, 612 | {.x = +FLOOR_HALF_SIZE, .y = 0.0f, .z = +FLOOR_HALF_SIZE} 613 | }; 614 | 615 | static const vector4f floor_color = { 616 | .r = 0.5f, .g = 0.5f, .b = 0.5f, .a = 1.0f 617 | }; 618 | 619 | static const vector3f floor_normal = { 620 | .x = 0.0f, .y = 1.0f, .z = 0.0f 621 | }; 622 | 623 | for (i = 0; i < 4; i++) { 624 | floor_mesh_data[i] = (struct mesh_vertex){floor_vertices[i], floor_normal, floor_color}; 625 | floor_indices_data[i] = i; 626 | } 627 | 628 | SceUID portal_mesh_uid; 629 | struct position_vertex *const portal_mesh_data = gpu_alloc_map( 630 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 631 | 4 * sizeof(struct position_vertex), &portal_mesh_uid); 632 | 633 | SceUID portal_indices_uid; 634 | unsigned short *const portal_indices_data = gpu_alloc_map( 635 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 636 | 4 * sizeof(unsigned short), &portal_indices_uid); 637 | 638 | #define PORTAL_SIZE 4.0f 639 | #define PORTAL_HALF_SIZE (PORTAL_SIZE / 2.0f) 640 | 641 | static const vector3f portal_vertices[] = { 642 | {.x = -PORTAL_HALF_SIZE, .y = +PORTAL_HALF_SIZE, .z = 0.0f}, 643 | {.x = -PORTAL_HALF_SIZE, .y = -PORTAL_HALF_SIZE, .z = 0.0f}, 644 | {.x = +PORTAL_HALF_SIZE, .y = +PORTAL_HALF_SIZE, .z = 0.0f}, 645 | {.x = +PORTAL_HALF_SIZE, .y = -PORTAL_HALF_SIZE, .z = 0.0f} 646 | }; 647 | 648 | static const vector3f portal_normal = { 649 | .x = 0.0f, .y = 0.0f, .z = -1.0f 650 | }; 651 | 652 | for (i = 0; i < 4; i++) { 653 | portal_mesh_data[i] = (struct position_vertex){portal_vertices[i]}; 654 | portal_indices_data[i] = i; 655 | } 656 | 657 | SceUID portal_frame_mesh_uid; 658 | portal_frame_mesh_data = gpu_alloc_map( 659 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 660 | 12 * sizeof(struct mesh_vertex), &portal_frame_mesh_uid); 661 | 662 | SceUID portal_frame_indices_uid; 663 | portal_frame_indices_data = gpu_alloc_map( 664 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_MEMORY_ATTRIB_READ, 665 | 8 * 3 * sizeof(unsigned short), &portal_frame_indices_uid); 666 | 667 | #define PORTAL_FRAME_SIZE 0.2f 668 | 669 | static const vector4f portal_frame_color = { 670 | .r = 0.3f, .g = 0.0f, .b = 1.0f, .a = 1.0f 671 | }; 672 | 673 | static const vector2f portal_frame_position_offsets[12] = { 674 | {.x = -PORTAL_HALF_SIZE - PORTAL_FRAME_SIZE, .y = +PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE}, 675 | {.x = -PORTAL_HALF_SIZE - PORTAL_FRAME_SIZE, .y = +PORTAL_HALF_SIZE}, 676 | {.x = +PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE, .y = +PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE}, 677 | {.x = +PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE, .y = +PORTAL_HALF_SIZE}, 678 | {.x = -PORTAL_HALF_SIZE - PORTAL_FRAME_SIZE, .y = -PORTAL_HALF_SIZE}, 679 | {.x = -PORTAL_HALF_SIZE, .y = +PORTAL_HALF_SIZE}, 680 | {.x = -PORTAL_HALF_SIZE, .y = -PORTAL_HALF_SIZE}, 681 | {.x = +PORTAL_HALF_SIZE, .y = +PORTAL_HALF_SIZE}, 682 | {.x = +PORTAL_HALF_SIZE, .y = -PORTAL_HALF_SIZE}, 683 | {.x = +PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE, .y = -PORTAL_HALF_SIZE}, 684 | {.x = -PORTAL_HALF_SIZE - PORTAL_FRAME_SIZE, .y = -PORTAL_HALF_SIZE - PORTAL_FRAME_SIZE}, 685 | {.x = +PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE, .y = -PORTAL_HALF_SIZE - PORTAL_FRAME_SIZE}, 686 | }; 687 | 688 | for (i = 0; i < 12; i++) { 689 | portal_frame_mesh_data[i] = (struct mesh_vertex){ 690 | .position = {.x = portal_frame_position_offsets[i].x, .y = portal_frame_position_offsets[i].y, .z = 0.0f}, 691 | .normal = portal_normal, 692 | .color = portal_frame_color 693 | }; 694 | } 695 | 696 | portal_frame_indices_data[0] = 0; 697 | portal_frame_indices_data[1] = 1; 698 | portal_frame_indices_data[2] = 2; 699 | portal_frame_indices_data[3] = 2; 700 | portal_frame_indices_data[4] = 1; 701 | portal_frame_indices_data[5] = 3; 702 | portal_frame_indices_data[6] = 1; 703 | portal_frame_indices_data[7] = 4; 704 | portal_frame_indices_data[8] = 5; 705 | portal_frame_indices_data[9] = 5; 706 | portal_frame_indices_data[10] = 4; 707 | portal_frame_indices_data[11] = 6; 708 | portal_frame_indices_data[12] = 7; 709 | portal_frame_indices_data[13] = 8; 710 | portal_frame_indices_data[14] = 3; 711 | portal_frame_indices_data[15] = 3; 712 | portal_frame_indices_data[16] = 8; 713 | portal_frame_indices_data[17] = 9; 714 | portal_frame_indices_data[18] = 4; 715 | portal_frame_indices_data[19] = 10; 716 | portal_frame_indices_data[20] = 9; 717 | portal_frame_indices_data[21] = 9; 718 | portal_frame_indices_data[22] = 10; 719 | portal_frame_indices_data[23] = 11; 720 | 721 | gxm_front_buffer_index = DISPLAY_BUFFER_COUNT - 1; 722 | gxm_back_buffer_index = 0; 723 | 724 | matrix4x4 projection_matrix; 725 | matrix4x4_init_perspective(projection_matrix, 90.0f, 726 | DISPLAY_WIDTH / (float)DISPLAY_HEIGHT, 0.01f, 100.0f); 727 | 728 | SceCtrlData pad; 729 | memset(&pad, 0, sizeof(pad)); 730 | 731 | static vector3f camera_initial_pos = { 732 | .x = 0.0f, .y = 3.0f, .z = 5.0f 733 | }; 734 | 735 | static vector3f camera_initial_rot = { 736 | //.x = -DEG_TO_RAD(20), .y = 0.0f, .z = 0.0f 737 | .x = 0.0f, .y = 0.0f, .z = 0.0f 738 | }; 739 | 740 | struct camera camera; 741 | camera_init(&camera, &camera_initial_pos, &camera_initial_rot); 742 | 743 | struct scene_state scene_state; 744 | scene_state.portal.width = PORTAL_SIZE; 745 | scene_state.portal.height = PORTAL_SIZE; 746 | 747 | static const vector3f portal_end1_translation = { 748 | .x = 0.0f, .y = PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE, .z = 0.0f 749 | }; 750 | static const vector3f portal_end1_rotation = { 751 | .x = 0.0f, .y = M_PI, .z = 0.0f 752 | }; 753 | 754 | matrix4x4_build_model_matrix(scene_state.portal.end1.model_matrix, 755 | &portal_end1_translation, &portal_end1_rotation); 756 | 757 | scene_state.portal_end2_translation.x = 0.0f; 758 | scene_state.portal_end2_translation.y = PORTAL_HALF_SIZE + PORTAL_FRAME_SIZE; 759 | scene_state.portal_end2_translation.z = 4.0f; 760 | scene_state.portal_end2_rotation.y = 0.0f; 761 | scene_state.portal_end2_rotation.x = 0.0f; 762 | scene_state.portal_end2_rotation.z = 0.0f; 763 | 764 | matrix4x4_build_model_matrix(scene_state.portal.end2.model_matrix, 765 | &scene_state.portal_end2_translation, &scene_state.portal_end2_rotation); 766 | 767 | scene_state.light_distance = 8.0f; 768 | scene_state.light_x_rot = DEG_TO_RAD(20.0f); 769 | scene_state.light_y_rot = 0.0f; 770 | 771 | static int run = 1; 772 | while (run) { 773 | sceCtrlPeekBufferPositive(0, &pad, 1); 774 | if (pad.buttons & SCE_CTRL_START) 775 | run = 0; 776 | 777 | update_camera(&camera, &pad); 778 | update_scene(&scene_state, &camera, &pad); 779 | 780 | sceGxmBeginScene(gxm_context, 781 | 0, 782 | gxm_render_target, 783 | NULL, 784 | NULL, 785 | gxm_sync_objects[gxm_back_buffer_index], 786 | &gxm_color_surfaces[gxm_back_buffer_index], 787 | &gxm_depth_stencil_surface); 788 | 789 | { /* Clear the color and the depth/stencil buffers */ 790 | sceGxmSetVertexProgram(gxm_context, gxm_clear_vertex_program_patched); 791 | sceGxmSetFragmentProgram(gxm_context, gxm_clear_fragment_program_patched); 792 | 793 | static const float clear_color[4] = { 794 | 1.0f, 1.0f, 1.0f, 1.0f 795 | }; 796 | 797 | set_fragment_default_uniform_data(gxm_clear_fragment_program_u_clear_color_param, 798 | sizeof(clear_color) / sizeof(float), clear_color); 799 | 800 | sceGxmSetFrontStencilFunc(gxm_context, 801 | SCE_GXM_STENCIL_FUNC_ALWAYS, 802 | SCE_GXM_STENCIL_OP_ZERO, 803 | SCE_GXM_STENCIL_OP_ZERO, 804 | SCE_GXM_STENCIL_OP_ZERO, 805 | 0, 0xFF); 806 | 807 | sceGxmSetVertexStream(gxm_context, 0, clear_vertices_data); 808 | sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, 809 | SCE_GXM_INDEX_FORMAT_U16, clear_indices_data, 4); 810 | } 811 | 812 | /* 813 | * Step 1: Disable drawing to the color buffer and the depth buffer, 814 | * but enable writing to the stencil buffer. 815 | * Step 2: Set the stencil operation to GL_INCR on sfail, meaning that 816 | * the stencil value will be incremented when the stencil test fails. 817 | * Step 3: Set the stencil function to GL_NEVER, which makes sure that 818 | * the stencil test always fails on every pixel drawn. 819 | */ 820 | sceGxmSetFrontDepthWriteEnable(gxm_context, 821 | SCE_GXM_DEPTH_WRITE_DISABLED); 822 | sceGxmSetFrontStencilFunc(gxm_context, 823 | SCE_GXM_STENCIL_FUNC_NEVER, 824 | SCE_GXM_STENCIL_OP_INCR, 825 | SCE_GXM_STENCIL_OP_KEEP, 826 | SCE_GXM_STENCIL_OP_KEEP, 827 | 0, 0xFF); 828 | 829 | /* 830 | * Step 4: Draw the portal's frame. At this point the stencil buffer is filled 831 | * with zero's on the outside of the portal's frame and one's on the inside. 832 | */ 833 | { 834 | sceGxmSetVertexProgram(gxm_context, gxm_disable_color_buffer_vertex_program_patched); 835 | sceGxmSetFragmentProgram(gxm_context, gxm_disable_color_buffer_fragment_program_patched); 836 | 837 | matrix4x4 portal_mvp_matrix; 838 | matrix4x4 portal_modelview_matrix; 839 | 840 | matrix4x4_multiply(portal_modelview_matrix, 841 | camera.view_matrix, scene_state.portal.end1.model_matrix); 842 | matrix4x4_multiply(portal_mvp_matrix, 843 | projection_matrix, portal_modelview_matrix); 844 | 845 | set_vertex_default_uniform_data(gxm_disable_color_buffer_vertex_program_u_mvp_matrix_param, 846 | sizeof(portal_mvp_matrix) / sizeof(float), portal_mvp_matrix); 847 | 848 | sceGxmSetVertexStream(gxm_context, 0, portal_mesh_data); 849 | sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, 850 | SCE_GXM_INDEX_FORMAT_U16, portal_indices_data, 4); 851 | } 852 | 853 | /* 854 | * Step 5: Generate the virtual camera's view matrix using the view 855 | * frustum clipping method. 856 | * Step 6: Disable writing to the stencil buffer, but enable drawing to 857 | * the color buffer and the depth buffer. 858 | * Step 7: Set the stencil function to GL_LEQUAL with reference value 1. 859 | * This will only draw where the stencil value is greater than 860 | * or equal to 1, which is inside the portal frame. 861 | * Step 8: Draw the scene using the virtual camera from step 5. This will 862 | * only draw inside of the portal's frame because of the stencil test. 863 | */ 864 | sceGxmSetFrontDepthWriteEnable(gxm_context, 865 | SCE_GXM_DEPTH_WRITE_ENABLED); 866 | sceGxmSetFrontStencilRef(gxm_context, 1); 867 | sceGxmSetFrontStencilFunc(gxm_context, 868 | SCE_GXM_STENCIL_FUNC_LESS_EQUAL, 869 | SCE_GXM_STENCIL_OP_KEEP, 870 | SCE_GXM_STENCIL_OP_KEEP, 871 | SCE_GXM_STENCIL_OP_KEEP, 872 | 0xFF, 0); 873 | { 874 | /* 875 | * Render the scene from the other portal's end view: 876 | * If V is the camera's view matrix, 877 | * M1 is the portal source model matrix, 878 | * M2 is the portal destination model matrix, 879 | * for non-static portals: 880 | * V' = V * M1 * ROT_Y_180 * M2^-1 881 | */ 882 | 883 | matrix4x4 end1_modelview; 884 | matrix4x4_multiply(end1_modelview, camera.view_matrix, scene_state.portal.end1.model_matrix); 885 | 886 | matrix4x4 rot_y_180; 887 | matrix4x4_init_rotation_y(rot_y_180, M_PI); 888 | 889 | matrix4x4 end1_modelview_rot_y_180; 890 | matrix4x4_multiply(end1_modelview_rot_y_180, end1_modelview, rot_y_180); 891 | 892 | matrix4x4 end2_model_inv; 893 | matrix4x4_invert(end2_model_inv, scene_state.portal.end2.model_matrix); 894 | 895 | matrix4x4 portal_end2_view_matrix; 896 | matrix4x4_multiply(portal_end2_view_matrix, end1_modelview_rot_y_180, end2_model_inv); 897 | 898 | /* 899 | * TODO: Clip projection's matrix zNear plane to 900 | * the portal's plane. 901 | */ 902 | 903 | draw_scene(&scene_state, projection_matrix, portal_end2_view_matrix); 904 | } 905 | 906 | /* 907 | * Step 9: Disable the stencil test, disable drawing to the color 908 | * buffer, and enable drawing to the depth buffer. 909 | * Step 10: Clear the depth buffer. 910 | */ 911 | sceGxmSetFrontDepthFunc(gxm_context, 912 | SCE_GXM_DEPTH_FUNC_ALWAYS); 913 | sceGxmSetFrontStencilFunc(gxm_context, 914 | SCE_GXM_STENCIL_FUNC_ALWAYS, 915 | SCE_GXM_STENCIL_OP_KEEP, 916 | SCE_GXM_STENCIL_OP_KEEP, 917 | SCE_GXM_STENCIL_OP_KEEP, 918 | 0, 0); 919 | 920 | { 921 | sceGxmSetVertexProgram(gxm_context, gxm_clear_vertex_program_patched); 922 | sceGxmSetFragmentProgram(gxm_context, gxm_disable_color_buffer_fragment_program_patched); 923 | 924 | sceGxmSetVertexStream(gxm_context, 0, clear_vertices_data); 925 | sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, 926 | SCE_GXM_INDEX_FORMAT_U16, clear_indices_data, 4); 927 | } 928 | 929 | sceGxmSetFrontDepthFunc(gxm_context, 930 | SCE_GXM_DEPTH_FUNC_LESS_EQUAL); 931 | 932 | /* 933 | * Step 10: Draw the portal frame once again, this time 934 | * to the depth buffer which was just cleared. 935 | */ 936 | { 937 | sceGxmSetVertexProgram(gxm_context, gxm_disable_color_buffer_vertex_program_patched); 938 | sceGxmSetFragmentProgram(gxm_context, gxm_disable_color_buffer_fragment_program_patched); 939 | 940 | matrix4x4 portal_mvp_matrix; 941 | matrix4x4 portal_modelview_matrix; 942 | 943 | matrix4x4_multiply(portal_modelview_matrix, 944 | camera.view_matrix, scene_state.portal.end1.model_matrix); 945 | matrix4x4_multiply(portal_mvp_matrix, 946 | projection_matrix, portal_modelview_matrix); 947 | 948 | set_vertex_default_uniform_data(gxm_disable_color_buffer_vertex_program_u_mvp_matrix_param, 949 | sizeof(portal_mvp_matrix) / sizeof(float), portal_mvp_matrix); 950 | 951 | sceGxmSetVertexStream(gxm_context, 0, portal_mesh_data); 952 | sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, 953 | SCE_GXM_INDEX_FORMAT_U16, portal_indices_data, 4); 954 | } 955 | 956 | /* 957 | * Step 11: Enable the color buffer again. 958 | * step 12: Draw the whole scene with the regular camera. 959 | */ 960 | 961 | draw_scene(&scene_state, projection_matrix, camera.view_matrix); 962 | 963 | sceGxmEndScene(gxm_context, NULL, NULL); 964 | 965 | sceGxmPadHeartbeat(&gxm_color_surfaces[gxm_back_buffer_index], 966 | gxm_sync_objects[gxm_back_buffer_index]); 967 | 968 | struct display_queue_callback_data queue_cb_data; 969 | queue_cb_data.addr = gxm_color_surfaces_addr[gxm_back_buffer_index]; 970 | 971 | sceGxmDisplayQueueAddEntry(gxm_sync_objects[gxm_front_buffer_index], 972 | gxm_sync_objects[gxm_back_buffer_index], &queue_cb_data); 973 | 974 | gxm_front_buffer_index = gxm_back_buffer_index; 975 | gxm_back_buffer_index = (gxm_back_buffer_index + 1) % DISPLAY_BUFFER_COUNT; 976 | } 977 | 978 | sceGxmDisplayQueueFinish(); 979 | sceGxmFinish(gxm_context); 980 | 981 | gpu_unmap_free(clear_vertices_uid); 982 | gpu_unmap_free(clear_indices_uid); 983 | 984 | gpu_unmap_free(cube_mesh_uid); 985 | gpu_unmap_free(cube_indices_uid); 986 | 987 | gpu_unmap_free(floor_mesh_uid); 988 | gpu_unmap_free(floor_indices_uid); 989 | 990 | gpu_unmap_free(portal_mesh_uid); 991 | gpu_unmap_free(portal_indices_uid); 992 | 993 | gpu_unmap_free(portal_frame_mesh_uid); 994 | gpu_unmap_free(portal_frame_indices_uid); 995 | 996 | sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, 997 | gxm_disable_color_buffer_vertex_program_patched); 998 | sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, 999 | gxm_disable_color_buffer_fragment_program_patched); 1000 | 1001 | sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, 1002 | gxm_clear_vertex_program_patched); 1003 | sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, 1004 | gxm_clear_fragment_program_patched); 1005 | 1006 | sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, 1007 | gxm_cube_vertex_program_patched); 1008 | sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, 1009 | gxm_cube_fragment_program_patched); 1010 | 1011 | sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, 1012 | gxm_clear_vertex_program_id); 1013 | sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, 1014 | gxm_clear_fragment_program_id); 1015 | 1016 | sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, 1017 | gxm_cube_vertex_program_id); 1018 | sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, 1019 | gxm_cube_fragment_program_id); 1020 | 1021 | sceGxmShaderPatcherDestroy(gxm_shader_patcher); 1022 | 1023 | gpu_unmap_free(gxm_shader_patcher_buffer_uid); 1024 | gpu_vertex_usse_unmap_free(gxm_shader_patcher_vertex_usse_uid); 1025 | gpu_fragment_usse_unmap_free(gxm_shader_patcher_fragment_usse_uid); 1026 | 1027 | gpu_unmap_free(gxm_depth_stencil_surface_uid); 1028 | 1029 | for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) { 1030 | gpu_unmap_free(gxm_color_surfaces_uid[i]); 1031 | sceGxmSyncObjectDestroy(gxm_sync_objects[i]); 1032 | } 1033 | 1034 | sceGxmDestroyRenderTarget(gxm_render_target); 1035 | 1036 | gpu_unmap_free(vdm_ring_buffer_uid); 1037 | gpu_unmap_free(vertex_ring_buffer_uid); 1038 | gpu_unmap_free(fragment_ring_buffer_uid); 1039 | gpu_fragment_usse_unmap_free(fragment_usse_ring_buffer_uid); 1040 | 1041 | sceGxmDestroyContext(gxm_context); 1042 | 1043 | sceGxmTerminate(); 1044 | 1045 | return 0; 1046 | } 1047 | 1048 | static void update_scene(struct scene_state *state, const struct camera *camera, SceCtrlData *pad) 1049 | { 1050 | if (pad->buttons & SCE_CTRL_UP) 1051 | state->portal_end2_translation.z -= 0.025f; 1052 | else if (pad->buttons & SCE_CTRL_DOWN) 1053 | state->portal_end2_translation.z += 0.025f; 1054 | 1055 | if (pad->buttons & SCE_CTRL_RIGHT) 1056 | state->portal_end2_translation.x += 0.025f; 1057 | else if (pad->buttons & SCE_CTRL_LEFT) 1058 | state->portal_end2_translation.x -= 0.025f; 1059 | 1060 | if (pad->buttons & SCE_CTRL_SQUARE) 1061 | state->portal_end2_rotation.y += 0.025f; 1062 | else if (pad->buttons & SCE_CTRL_CIRCLE) 1063 | state->portal_end2_rotation.y -= 0.025f; 1064 | 1065 | if (pad->buttons & SCE_CTRL_CROSS) 1066 | state->portal_end2_rotation.x += 0.025f; 1067 | else if (pad->buttons & SCE_CTRL_TRIANGLE) 1068 | state->portal_end2_rotation.x -= 0.025f; 1069 | 1070 | /* 1071 | * Update the portal's other end model matrix. 1072 | */ 1073 | matrix4x4_build_model_matrix(state->portal.end2.model_matrix, 1074 | &state->portal_end2_translation, &state->portal_end2_rotation); 1075 | 1076 | /* 1077 | * Update light's attributes. 1078 | */ 1079 | vector3f light_position; 1080 | light_position.x = state->light_distance * cosf(state->light_x_rot) * cosf(state->light_y_rot); 1081 | light_position.y = state->light_distance * sinf(state->light_x_rot); 1082 | light_position.z = state->light_distance * cosf(state->light_x_rot) * sinf(state->light_y_rot); 1083 | 1084 | state->light_y_rot += 0.1f; 1085 | vector3f_matrix4x4_mult(&state->light.position, 1086 | camera->view_matrix, &light_position, 1.0f); 1087 | 1088 | state->light.color = (vector3f){.r = 1.0f, .g = 1.0f, .b = 1.0f}; 1089 | } 1090 | 1091 | static void draw_scene(const struct scene_state *state, matrix4x4 projection_matrix, matrix4x4 view_matrix) 1092 | { 1093 | sceGxmSetVertexProgram(gxm_context, gxm_cube_vertex_program_patched); 1094 | sceGxmSetFragmentProgram(gxm_context, gxm_cube_fragment_program_patched); 1095 | 1096 | { /* Draw the portal frame */ 1097 | static const struct phong_material portal_frame_material = { 1098 | .ambient = {.r = 0.2f, .g = 0.2f, .b = 0.2f}, 1099 | .diffuse = {.r = 0.6f, .g = 0.6f, .b = 0.6f}, 1100 | .specular = {.r = 0.6f, .g = 0.6f, .b = 0.6f}, 1101 | .shininess = 40.0f 1102 | }; 1103 | 1104 | matrix4x4 portal_frame_mvp_matrix; 1105 | matrix4x4 portal_frame_modelview_matrix; 1106 | matrix3x3 portal_frame_normal_matrix; 1107 | 1108 | matrix4x4_multiply(portal_frame_modelview_matrix, view_matrix, state->portal.end1.model_matrix); 1109 | matrix4x4_multiply(portal_frame_mvp_matrix, projection_matrix, portal_frame_modelview_matrix); 1110 | matrix3x3_normal_matrix(portal_frame_normal_matrix, portal_frame_modelview_matrix); 1111 | 1112 | set_cube_fragment_light_uniform_params(&state->light, 1113 | &gxm_cube_fragment_program_light_params); 1114 | set_cube_fragment_material_uniform_params(&portal_frame_material, 1115 | &gxm_cube_fragment_program_phong_material_params); 1116 | set_cube_matrices_uniform_params(portal_frame_mvp_matrix, 1117 | portal_frame_modelview_matrix, portal_frame_normal_matrix); 1118 | 1119 | sceGxmSetVertexStream(gxm_context, 0, portal_frame_mesh_data); 1120 | sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLES, 1121 | SCE_GXM_INDEX_FORMAT_U16, portal_frame_indices_data, 24); 1122 | } 1123 | 1124 | { /* Draw the cube */ 1125 | static const struct phong_material cube1_material = { 1126 | .ambient = {.r = 0.1f, .g = 0.1f, .b = 0.1f}, 1127 | .diffuse = {.r = 0.8f, .g = 0.8f, .b = 0.8f}, 1128 | .specular = {.r = 0.6f, .g = 0.6f, .b = 0.6f}, 1129 | .shininess = 80.0f 1130 | }; 1131 | 1132 | matrix4x4 cube1_model_matrix; 1133 | matrix4x4_init_translation(cube1_model_matrix, 1134 | 5.0f, CUBE_SIZE + 0.1f, 0.0f); 1135 | 1136 | draw_cube(state, projection_matrix, view_matrix, 1137 | cube1_model_matrix, &cube1_material); 1138 | 1139 | static const struct phong_material cube2_material = { 1140 | .ambient = {.r = 0.1f, .g = 0.1f, .b = 0.1f}, 1141 | .diffuse = {.r = 0.8f, .g = 0.8f, .b = 0.8f}, 1142 | .specular = {.r = 0.6f, .g = 0.6f, .b = 0.6f}, 1143 | .shininess = 80.0f 1144 | }; 1145 | 1146 | matrix4x4 cube2_model_matrix; 1147 | matrix4x4_init_translation(cube2_model_matrix, 0.0f, 2.0f, 1.5f); 1148 | 1149 | draw_cube(state, projection_matrix, view_matrix, 1150 | cube2_model_matrix, &cube2_material); 1151 | } 1152 | 1153 | { /* Draw the floor */ 1154 | static const struct phong_material floor_material = { 1155 | .ambient = {.r = 0.1f, .g = 0.1f, .b = 0.1f}, 1156 | .diffuse = {.r = 0.8f, .g = 0.8f, .b = 0.8f}, 1157 | .specular = {.r = 0.7f, .g = 0.7f, .b = 0.7f}, 1158 | .shininess = 20.0f 1159 | }; 1160 | 1161 | matrix4x4 floor_mvp_matrix; 1162 | matrix4x4 floor_modelview_matrix; 1163 | matrix3x3 floor_normal_matrix; 1164 | matrix4x4 floor_model_matrix; 1165 | 1166 | matrix4x4_identity(floor_model_matrix); 1167 | matrix4x4_multiply(floor_modelview_matrix, view_matrix, floor_model_matrix); 1168 | matrix4x4_multiply(floor_mvp_matrix, projection_matrix, floor_modelview_matrix); 1169 | matrix3x3_normal_matrix(floor_normal_matrix, floor_modelview_matrix); 1170 | 1171 | set_cube_fragment_light_uniform_params(&state->light, 1172 | &gxm_cube_fragment_program_light_params); 1173 | set_cube_fragment_material_uniform_params(&floor_material, 1174 | &gxm_cube_fragment_program_phong_material_params); 1175 | set_cube_matrices_uniform_params(floor_mvp_matrix, 1176 | floor_modelview_matrix, floor_normal_matrix); 1177 | 1178 | sceGxmSetVertexStream(gxm_context, 0, floor_mesh_data); 1179 | sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, 1180 | SCE_GXM_INDEX_FORMAT_U16, floor_indices_data, 4); 1181 | } 1182 | } 1183 | 1184 | static void update_camera(struct camera *camera, SceCtrlData *pad) 1185 | { 1186 | vector3f camera_look; 1187 | vector3f camera_right; 1188 | 1189 | camera_get_look_vector(camera, &camera_look); 1190 | camera_get_right_vector(camera, &camera_right); 1191 | 1192 | float forward = 0.0f; 1193 | float lateral = 0.0f; 1194 | 1195 | signed char lx = (signed char)pad->lx - 128; 1196 | if (abs(lx) > ANALOG_THRESHOLD) 1197 | lateral = lx / 1536.0f; 1198 | 1199 | signed char ly = (signed char)pad->ly - 128; 1200 | if (abs(ly) > ANALOG_THRESHOLD) 1201 | forward = ly / 1536.0f; 1202 | 1203 | signed char rx = (signed char)pad->rx - 128; 1204 | if (abs(rx) > ANALOG_THRESHOLD) 1205 | camera->rotation.y -= rx / 1536.0f; 1206 | 1207 | signed char ry = (signed char)pad->ry - 128; 1208 | if (abs(ry) > ANALOG_THRESHOLD) 1209 | camera->rotation.x -= ry / 1536.0f; 1210 | 1211 | if (pad->buttons & SCE_CTRL_RTRIGGER) 1212 | camera->position.y += 0.1f; 1213 | else if (pad->buttons & SCE_CTRL_LTRIGGER) 1214 | camera->position.y -= 0.1f; 1215 | 1216 | vector3f_add_mult(&camera->position, &camera_look, forward); 1217 | vector3f_add_mult(&camera->position, &camera_right, lateral); 1218 | 1219 | camera_update_view_matrix(camera); 1220 | } 1221 | 1222 | static void draw_cube(const struct scene_state *state, const matrix4x4 projection_matrix, 1223 | const matrix4x4 view_matrix, const matrix4x4 model_matrix, const struct phong_material *material) 1224 | { 1225 | matrix4x4 mvp_matrix; 1226 | matrix4x4 modelview_matrix; 1227 | matrix3x3 normal_matrix; 1228 | 1229 | matrix4x4_multiply(modelview_matrix, view_matrix, model_matrix); 1230 | matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix); 1231 | matrix3x3_normal_matrix(normal_matrix, modelview_matrix); 1232 | 1233 | set_cube_fragment_light_uniform_params(&state->light, 1234 | &gxm_cube_fragment_program_light_params); 1235 | set_cube_fragment_material_uniform_params(material, 1236 | &gxm_cube_fragment_program_phong_material_params); 1237 | set_cube_matrices_uniform_params(mvp_matrix, 1238 | modelview_matrix, normal_matrix); 1239 | 1240 | sceGxmSetVertexStream(gxm_context, 0, cube_mesh_data); 1241 | sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLES, 1242 | SCE_GXM_INDEX_FORMAT_U16, cube_indices_data, 36); 1243 | } 1244 | 1245 | static void set_cube_fragment_light_uniform_params(const struct light *light, 1246 | const struct light_gxm_params *params) 1247 | { 1248 | set_fragment_default_uniform_data(params->position, 1249 | sizeof(light->position) / sizeof(float), &light->position); 1250 | set_fragment_default_uniform_data(params->color, 1251 | sizeof(light->color) / sizeof(float), &light->color); 1252 | } 1253 | 1254 | static void set_cube_matrices_uniform_params(matrix4x4 mvp_matrix, 1255 | matrix4x4 modelview_matrix, matrix3x3 normal_matrix) 1256 | { 1257 | set_vertex_default_uniform_data(gxm_cube_vertex_program_u_mvp_matrix_param, 1258 | sizeof(matrix4x4) / sizeof(float), mvp_matrix); 1259 | set_fragment_default_uniform_data(gxm_cube_fragment_program_u_modelview_matrix_param, 1260 | sizeof(matrix4x4) / sizeof(float), modelview_matrix); 1261 | set_fragment_default_uniform_data(gxm_cube_fragment_program_u_normal_matrix_param, 1262 | sizeof(matrix3x3) / sizeof(float), normal_matrix); 1263 | } 1264 | 1265 | static void set_cube_fragment_material_uniform_params(const struct phong_material *material, 1266 | const struct phong_material_gxm_params *params) 1267 | { 1268 | set_fragment_default_uniform_data(params->ambient, 1269 | sizeof(material->ambient) / sizeof(float), &material->ambient); 1270 | set_fragment_default_uniform_data(params->diffuse, 1271 | sizeof(material->diffuse) / sizeof(float), &material->diffuse); 1272 | set_fragment_default_uniform_data(params->specular, 1273 | sizeof(material->specular) / sizeof(float), &material->specular); 1274 | set_fragment_default_uniform_data(params->shininess, 1275 | sizeof(material->shininess) / sizeof(float), &material->shininess); 1276 | } 1277 | 1278 | void set_vertex_default_uniform_data(const SceGxmProgramParameter *param, 1279 | unsigned int component_count, const void *data) 1280 | { 1281 | void *uniform_buffer; 1282 | sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &uniform_buffer); 1283 | sceGxmSetUniformDataF(uniform_buffer, param, 0, component_count, data); 1284 | } 1285 | 1286 | void set_fragment_default_uniform_data(const SceGxmProgramParameter *param, 1287 | unsigned int component_count, const void *data) 1288 | { 1289 | void *uniform_buffer; 1290 | sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &uniform_buffer); 1291 | sceGxmSetUniformDataF(uniform_buffer, param, 0, component_count, data); 1292 | } 1293 | 1294 | void *gpu_alloc_map(SceKernelMemBlockType type, SceGxmMemoryAttribFlags gpu_attrib, size_t size, SceUID *uid) 1295 | { 1296 | SceUID memuid; 1297 | void *addr; 1298 | 1299 | if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) 1300 | size = ALIGN(size, 256 * 1024); 1301 | else 1302 | size = ALIGN(size, 4 * 1024); 1303 | 1304 | memuid = sceKernelAllocMemBlock("gpumem", type, size, NULL); 1305 | if (memuid < 0) 1306 | return NULL; 1307 | 1308 | if (sceKernelGetMemBlockBase(memuid, &addr) < 0) 1309 | return NULL; 1310 | 1311 | if (sceGxmMapMemory(addr, size, gpu_attrib) < 0) { 1312 | sceKernelFreeMemBlock(memuid); 1313 | return NULL; 1314 | } 1315 | 1316 | if (uid) 1317 | *uid = memuid; 1318 | 1319 | return addr; 1320 | } 1321 | 1322 | void gpu_unmap_free(SceUID uid) 1323 | { 1324 | void *addr; 1325 | 1326 | if (sceKernelGetMemBlockBase(uid, &addr) < 0) 1327 | return; 1328 | 1329 | sceGxmUnmapMemory(addr); 1330 | 1331 | sceKernelFreeMemBlock(uid); 1332 | } 1333 | 1334 | void *gpu_vertex_usse_alloc_map(size_t size, SceUID *uid, unsigned int *usse_offset) 1335 | { 1336 | SceUID memuid; 1337 | void *addr; 1338 | 1339 | size = ALIGN(size, 4 * 1024); 1340 | 1341 | memuid = sceKernelAllocMemBlock("gpu_vertex_usse", 1342 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL); 1343 | if (memuid < 0) 1344 | return NULL; 1345 | 1346 | if (sceKernelGetMemBlockBase(memuid, &addr) < 0) 1347 | return NULL; 1348 | 1349 | if (sceGxmMapVertexUsseMemory(addr, size, usse_offset) < 0) 1350 | return NULL; 1351 | 1352 | if (uid) 1353 | *uid = memuid; 1354 | 1355 | return addr; 1356 | } 1357 | 1358 | void gpu_vertex_usse_unmap_free(SceUID uid) 1359 | { 1360 | void *addr; 1361 | 1362 | if (sceKernelGetMemBlockBase(uid, &addr) < 0) 1363 | return; 1364 | 1365 | sceGxmUnmapVertexUsseMemory(addr); 1366 | 1367 | sceKernelFreeMemBlock(uid); 1368 | } 1369 | 1370 | void *gpu_fragment_usse_alloc_map(size_t size, SceUID *uid, unsigned int *usse_offset) 1371 | { 1372 | SceUID memuid; 1373 | void *addr; 1374 | 1375 | size = ALIGN(size, 4 * 1024); 1376 | 1377 | memuid = sceKernelAllocMemBlock("gpu_fragment_usse", 1378 | SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL); 1379 | if (memuid < 0) 1380 | return NULL; 1381 | 1382 | if (sceKernelGetMemBlockBase(memuid, &addr) < 0) 1383 | return NULL; 1384 | 1385 | if (sceGxmMapFragmentUsseMemory(addr, size, usse_offset) < 0) 1386 | return NULL; 1387 | 1388 | if (uid) 1389 | *uid = memuid; 1390 | 1391 | return addr; 1392 | } 1393 | 1394 | void gpu_fragment_usse_unmap_free(SceUID uid) 1395 | { 1396 | void *addr; 1397 | 1398 | if (sceKernelGetMemBlockBase(uid, &addr) < 0) 1399 | return; 1400 | 1401 | sceGxmUnmapFragmentUsseMemory(addr); 1402 | 1403 | sceKernelFreeMemBlock(uid); 1404 | } 1405 | 1406 | void *shader_patcher_host_alloc_cb(void *user_data, unsigned int size) 1407 | { 1408 | return malloc(size); 1409 | } 1410 | 1411 | void shader_patcher_host_free_cb(void *user_data, void *mem) 1412 | { 1413 | return free(mem); 1414 | } 1415 | 1416 | void display_queue_callback(const void *callbackData) 1417 | { 1418 | SceDisplayFrameBuf display_fb; 1419 | const struct display_queue_callback_data *cb_data = callbackData; 1420 | 1421 | memset(&display_fb, 0, sizeof(display_fb)); 1422 | display_fb.size = sizeof(display_fb); 1423 | display_fb.base = cb_data->addr; 1424 | display_fb.pitch = DISPLAY_STRIDE; 1425 | display_fb.pixelformat = DISPLAY_PIXEL_FORMAT; 1426 | display_fb.width = DISPLAY_WIDTH; 1427 | display_fb.height = DISPLAY_HEIGHT; 1428 | 1429 | sceDisplaySetFrameBuf(&display_fb, SCE_DISPLAY_SETBUF_NEXTFRAME); 1430 | 1431 | sceDisplayWaitVblankStart(); 1432 | } 1433 | -------------------------------------------------------------------------------- /source/math_utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "math_utils.h" 4 | 5 | /* 6 | * Note: matrices are row-major. 7 | */ 8 | 9 | static inline float sgn(float a) 10 | { 11 | if (a > 0.0f) 12 | return 1.0f; 13 | if (a < 0.0f) 14 | return -1.0f; 15 | return 0.0f; 16 | } 17 | 18 | void vector3f_init(vector3f *v, float x, float y, float z) 19 | { 20 | v->x = x; 21 | v->y = y; 22 | v->z = z; 23 | } 24 | 25 | void vector3f_copy(vector3f *dst, const vector3f *src) 26 | { 27 | dst->x = src->x; 28 | dst->y = src->y; 29 | dst->z = src->z; 30 | } 31 | 32 | float vector3f_length(const vector3f *v) 33 | { 34 | return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); 35 | } 36 | 37 | void vector3f_add(vector3f *v1, const vector3f *v2) 38 | { 39 | v1->x += v2->x; 40 | v1->y += v2->y; 41 | v1->z += v2->z; 42 | } 43 | 44 | void vector3f_scalar_mult(vector3f *v, float a) 45 | { 46 | v->x *= a; 47 | v->y *= a; 48 | v->z *= a; 49 | } 50 | 51 | void vector3f_add_mult(vector3f *v, const vector3f *u, float a) 52 | { 53 | v->x += u->x * a; 54 | v->y += u->y * a; 55 | v->z += u->z * a; 56 | } 57 | 58 | void vector3f_opposite(vector3f *v1, const vector3f *v0) 59 | { 60 | v1->x = -v0->x; 61 | v1->y = -v0->y; 62 | v1->z = -v0->z; 63 | } 64 | 65 | float vector3f_dot_product(const vector3f *v1, const vector3f *v2) 66 | { 67 | return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z; 68 | } 69 | 70 | void vector3f_cross_product(vector3f *w, const vector3f *u, const vector3f *v) 71 | { 72 | w->x = u->y * v->z - u->z * v->y; 73 | w->y = u->z * v->x - u->x * v->z; 74 | w->z = u->x * v->y - u->y * v->x; 75 | } 76 | 77 | void vector3f_matrix4x4_mult(vector3f *u, const matrix4x4 m, const vector3f *v, float w) 78 | { 79 | u->x = m[0][0] * v->x + m[0][1] * v->y + m[0][2] * v->z + m[0][3] * w; 80 | u->y = m[1][0] * v->x + m[1][1] * v->y + m[1][2] * v->z + m[1][3] * w; 81 | u->z = m[2][0] * v->x + m[2][1] * v->y + m[2][2] * v->z + m[2][3] * w; 82 | } 83 | 84 | void vector4f_init(vector4f *v, float x, float y, float z, float w) 85 | { 86 | v->x = x; 87 | v->y = y; 88 | v->z = z; 89 | v->w = w; 90 | } 91 | 92 | void vector4f_scalar_mult_dest(vector4f *u, const vector4f *v, float a) 93 | { 94 | u->x = v->x * a; 95 | u->y = v->y * a; 96 | u->z = v->z * a; 97 | u->w = v->w * a; 98 | } 99 | 100 | float vector4f_dot_product(const vector4f *v1, const vector4f *v2) 101 | { 102 | return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z + v1->w * v2->w; 103 | } 104 | 105 | void vector4f_matrix4x4_mult(vector4f *u, const matrix4x4 m, const vector4f *v) 106 | { 107 | u->x = m[0][0] * v->x + m[0][1] * v->y + m[0][2] * v->z + m[0][3] * v->w; 108 | u->y = m[1][0] * v->x + m[1][1] * v->y + m[1][2] * v->z + m[1][3] * v->w; 109 | u->z = m[2][0] * v->x + m[2][1] * v->y + m[2][2] * v->z + m[2][3] * v->w; 110 | u->w = m[3][0] * v->x + m[3][1] * v->y + m[3][2] * v->z + m[3][3] * v->w; 111 | } 112 | 113 | void matrix3x3_identity(matrix3x3 m) 114 | { 115 | m[0][1] = m[0][2] = 0.0f; 116 | m[1][0] = m[1][2] = 0.0f; 117 | m[2][0] = m[2][1] = 0.0f; 118 | m[0][0] = m[1][1] = m[2][2] = 1.0f; 119 | } 120 | 121 | void matrix3x3_from_matrix4x4(matrix3x3 dst, const matrix4x4 src) 122 | { 123 | int i, j; 124 | 125 | for (i = 0; i < 3; i++) { 126 | for (j = 0; j < 3; j++) 127 | dst[i][j] = src[i][j]; 128 | } 129 | } 130 | 131 | void matrix4x4_identity(matrix4x4 m) 132 | { 133 | m[0][1] = m[0][2] = m[0][3] = 0.0f; 134 | m[1][0] = m[1][2] = m[1][3] = 0.0f; 135 | m[2][0] = m[2][1] = m[2][3] = 0.0f; 136 | m[3][0] = m[3][1] = m[3][2] = 0.0f; 137 | m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; 138 | } 139 | 140 | void matrix4x4_copy(matrix4x4 dst, const matrix4x4 src) 141 | { 142 | memcpy(dst, src, sizeof(matrix4x4)); 143 | } 144 | 145 | void matrix4x4_multiply(matrix4x4 dst, const matrix4x4 src1, const matrix4x4 src2) 146 | { 147 | int i, j, k; 148 | 149 | for (i = 0; i < 4; i++) { 150 | for (j = 0; j < 4; j++) { 151 | dst[i][j] = 0.0f; 152 | for (k = 0; k < 4; k++) 153 | dst[i][j] += src1[i][k] * src2[k][j]; 154 | } 155 | } 156 | } 157 | 158 | void matrix4x4_init_rotation_x(matrix4x4 m, float rad) 159 | { 160 | float c = cosf(rad); 161 | float s = sinf(rad); 162 | 163 | matrix4x4_identity(m); 164 | 165 | m[1][1] = c; 166 | m[1][2] = -s; 167 | m[2][1] = s; 168 | m[2][2] = c; 169 | } 170 | 171 | void matrix4x4_init_rotation_y(matrix4x4 m, float rad) 172 | { 173 | float c = cosf(rad); 174 | float s = sinf(rad); 175 | 176 | matrix4x4_identity(m); 177 | 178 | m[0][0] = c; 179 | m[0][2] = s; 180 | m[2][0] = -s; 181 | m[2][2] = c; 182 | } 183 | 184 | 185 | void matrix4x4_init_rotation_z(matrix4x4 m, float rad) 186 | { 187 | float c = cosf(rad); 188 | float s = sinf(rad); 189 | 190 | matrix4x4_identity(m); 191 | 192 | m[0][0] = c; 193 | m[0][1] = -s; 194 | m[1][0] = s; 195 | m[1][1] = c; 196 | } 197 | 198 | void matrix4x4_rotate_x(matrix4x4 m, float rad) 199 | { 200 | matrix4x4 m1, m2; 201 | 202 | matrix4x4_init_rotation_x(m1, rad); 203 | matrix4x4_multiply(m2, m, m1); 204 | matrix4x4_copy(m, m2); 205 | } 206 | 207 | 208 | void matrix4x4_rotate_y(matrix4x4 m, float rad) 209 | { 210 | matrix4x4 m1, m2; 211 | 212 | matrix4x4_init_rotation_y(m1, rad); 213 | matrix4x4_multiply(m2, m, m1); 214 | matrix4x4_copy(m, m2); 215 | } 216 | 217 | void matrix4x4_rotate_z(matrix4x4 m, float rad) 218 | { 219 | matrix4x4 m1, m2; 220 | 221 | matrix4x4_init_rotation_z(m1, rad); 222 | matrix4x4_multiply(m2, m, m1); 223 | matrix4x4_copy(m, m2); 224 | } 225 | 226 | void matrix4x4_init_translation(matrix4x4 m, float x, float y, float z) 227 | { 228 | matrix4x4_identity(m); 229 | 230 | m[0][3] = x; 231 | m[1][3] = y; 232 | m[2][3] = z; 233 | } 234 | 235 | void matrix4x4_init_translation_vector3f(matrix4x4 m, const vector3f *v) 236 | { 237 | matrix4x4_identity(m); 238 | 239 | m[0][3] = v->x; 240 | m[1][3] = v->y; 241 | m[2][3] = v->z; 242 | } 243 | 244 | void matrix4x4_translate(matrix4x4 m, float x, float y, float z) 245 | { 246 | matrix4x4 m1, m2; 247 | 248 | matrix4x4_init_translation(m1, x, y, z); 249 | matrix4x4_multiply(m2, m, m1); 250 | matrix4x4_copy(m, m2); 251 | } 252 | 253 | void matrix4x4_init_scaling(matrix4x4 m, float scale_x, float scale_y, float scale_z) 254 | { 255 | matrix4x4_identity(m); 256 | 257 | m[0][0] = scale_x; 258 | m[1][1] = scale_y; 259 | m[2][2] = scale_z; 260 | } 261 | 262 | void matrix4x4_scale(matrix4x4 m, float scale_x, float scale_y, float scale_z) 263 | { 264 | matrix4x4 m1, m2; 265 | 266 | matrix4x4_init_scaling(m1, scale_x, scale_y, scale_z); 267 | matrix4x4_multiply(m2, m, m1); 268 | matrix4x4_copy(m, m2); 269 | } 270 | 271 | void matrix4x4_reflect_origin(matrix4x4 m) 272 | { 273 | matrix4x4_scale(m, -1.0f, -1.0f, -1.0f); 274 | } 275 | 276 | void matrix4x4_transpose(matrix4x4 out, const matrix4x4 m) 277 | { 278 | int i, j; 279 | 280 | for (i = 0; i < 4; i++) { 281 | for (j = 0; j < 4; j++) 282 | out[i][j] = m[j][i]; 283 | } 284 | } 285 | 286 | int matrix4x4_invert(matrix4x4 out, const matrix4x4 m) 287 | { 288 | int i, j; 289 | float det; 290 | matrix4x4 inv; 291 | 292 | inv[0][0] = m[1][1] * m[2][2] * m[3][3] - 293 | m[1][1] * m[3][2] * m[2][3] - 294 | m[1][2] * m[2][1] * m[3][3] + 295 | m[1][2] * m[3][1] * m[2][3] + 296 | m[1][3] * m[2][1] * m[3][2] - 297 | m[1][3] * m[3][1] * m[2][2]; 298 | 299 | inv[0][1] = -m[0][1] * m[2][2] * m[3][3] + 300 | m[0][1] * m[3][2] * m[2][3] + 301 | m[0][2] * m[2][1] * m[3][3] - 302 | m[0][2] * m[3][1] * m[2][3] - 303 | m[0][3] * m[2][1] * m[3][2] + 304 | m[0][3] * m[3][1] * m[2][2]; 305 | 306 | inv[0][2] = m[0][1] * m[1][2] * m[3][3] - 307 | m[0][1] * m[3][2] * m[1][3] - 308 | m[0][2] * m[1][1] * m[3][3] + 309 | m[0][2] * m[3][1] * m[1][3] + 310 | m[0][3] * m[1][1] * m[3][2] - 311 | m[0][3] * m[3][1] * m[1][2]; 312 | 313 | inv[0][3] = -m[0][1] * m[1][2] * m[2][3] + 314 | m[0][1] * m[2][2] * m[1][3] + 315 | m[0][2] * m[1][1] * m[2][3] - 316 | m[0][2] * m[2][1] * m[1][3] - 317 | m[0][3] * m[1][1] * m[2][2] + 318 | m[0][3] * m[2][1] * m[1][2]; 319 | 320 | inv[1][0] = -m[1][0] * m[2][2] * m[3][3] + 321 | m[1][0] * m[3][2] * m[2][3] + 322 | m[1][2] * m[2][0] * m[3][3] - 323 | m[1][2] * m[3][0] * m[2][3] - 324 | m[1][3] * m[2][0] * m[3][2] + 325 | m[1][3] * m[3][0] * m[2][2]; 326 | 327 | inv[1][1] = m[0][0] * m[2][2] * m[3][3] - 328 | m[0][0] * m[3][2] * m[2][3] - 329 | m[0][2] * m[2][0] * m[3][3] + 330 | m[0][2] * m[3][0] * m[2][3] + 331 | m[0][3] * m[2][0] * m[3][2] - 332 | m[0][3] * m[3][0] * m[2][2]; 333 | 334 | inv[1][2] = -m[0][0] * m[1][2] * m[3][3] + 335 | m[0][0] * m[3][2] * m[1][3] + 336 | m[0][2] * m[1][0] * m[3][3] - 337 | m[0][2] * m[3][0] * m[1][3] - 338 | m[0][3] * m[1][0] * m[3][2] + 339 | m[0][3] * m[3][0] * m[1][2]; 340 | 341 | inv[1][3] = m[0][0] * m[1][2] * m[2][3] - 342 | m[0][0] * m[2][2] * m[1][3] - 343 | m[0][2] * m[1][0] * m[2][3] + 344 | m[0][2] * m[2][0] * m[1][3] + 345 | m[0][3] * m[1][0] * m[2][2] - 346 | m[0][3] * m[2][0] * m[1][2]; 347 | 348 | inv[2][0] = m[1][0] * m[2][1] * m[3][3] - 349 | m[1][0] * m[3][1] * m[2][3] - 350 | m[1][1] * m[2][0] * m[3][3] + 351 | m[1][1] * m[3][0] * m[2][3] + 352 | m[1][3] * m[2][0] * m[3][1] - 353 | m[1][3] * m[3][0] * m[2][1]; 354 | 355 | inv[2][1] = -m[0][0] * m[2][1] * m[3][3] + 356 | m[0][0] * m[3][1] * m[2][3] + 357 | m[0][1] * m[2][0] * m[3][3] - 358 | m[0][1] * m[3][0] * m[2][3] - 359 | m[0][3] * m[2][0] * m[3][1] + 360 | m[0][3] * m[3][0] * m[2][1]; 361 | 362 | inv[2][2] = m[0][0] * m[1][1] * m[3][3] - 363 | m[0][0] * m[3][1] * m[1][3] - 364 | m[0][1] * m[1][0] * m[3][3] + 365 | m[0][1] * m[3][0] * m[1][3] + 366 | m[0][3] * m[1][0] * m[3][1] - 367 | m[0][3] * m[3][0] * m[1][1]; 368 | 369 | inv[2][3] = -m[0][0] * m[1][1] * m[2][3] + 370 | m[0][0] * m[2][1] * m[1][3] + 371 | m[0][1] * m[1][0] * m[2][3] - 372 | m[0][1] * m[2][0] * m[1][3] - 373 | m[0][3] * m[1][0] * m[2][1] + 374 | m[0][3] * m[2][0] * m[1][1]; 375 | 376 | inv[3][0] = -m[1][0] * m[2][1] * m[3][2] + 377 | m[1][0] * m[3][1] * m[2][2] + 378 | m[1][1] * m[2][0] * m[3][2] - 379 | m[1][1] * m[3][0] * m[2][2] - 380 | m[1][2] * m[2][0] * m[3][1] + 381 | m[1][2] * m[3][0] * m[2][1]; 382 | 383 | inv[3][1] = m[0][0] * m[2][1] * m[3][2] - 384 | m[0][0] * m[3][1] * m[2][2] - 385 | m[0][1] * m[2][0] * m[3][2] + 386 | m[0][1] * m[3][0] * m[2][2] + 387 | m[0][2] * m[2][0] * m[3][1] - 388 | m[0][2] * m[3][0] * m[2][1]; 389 | 390 | inv[3][2] = -m[0][0] * m[1][1] * m[3][2] + 391 | m[0][0] * m[3][1] * m[1][2] + 392 | m[0][1] * m[1][0] * m[3][2] - 393 | m[0][1] * m[3][0] * m[1][2] - 394 | m[0][2] * m[1][0] * m[3][1] + 395 | m[0][2] * m[3][0] * m[1][1]; 396 | 397 | inv[3][3] = m[0][0] * m[1][1] * m[2][2] - 398 | m[0][0] * m[2][1] * m[1][2] - 399 | m[0][1] * m[1][0] * m[2][2] + 400 | m[0][1] * m[2][0] * m[1][2] + 401 | m[0][2] * m[1][0] * m[2][1] - 402 | m[0][2] * m[2][0] * m[1][1]; 403 | 404 | det = m[0][0] * inv[0][0] + m[1][0] * inv[0][1] + m[2][0] * inv[0][2] + m[3][0] * inv[0][3]; 405 | 406 | if (det == 0) 407 | return 0; 408 | 409 | det = 1.0 / det; 410 | 411 | for (i = 0; i < 4; i++) { 412 | for (j = 0; j < 4; j++) 413 | out[i][j] = inv[i][j] * det; 414 | } 415 | 416 | return 1; 417 | } 418 | 419 | void matrix4x4_get_x_axis(const matrix4x4 m, vector3f *x_axis) 420 | { 421 | x_axis->x = m[0][0]; 422 | x_axis->y = m[0][1]; 423 | x_axis->z = m[0][2]; 424 | } 425 | 426 | void matrix4x4_get_y_axis(const matrix4x4 m, vector3f *y_axis) 427 | { 428 | y_axis->x = m[1][0]; 429 | y_axis->y = m[1][1]; 430 | y_axis->z = m[1][2]; 431 | } 432 | 433 | void matrix4x4_get_z_axis(const matrix4x4 m, vector3f *z_axis) 434 | { 435 | z_axis->x = m[2][0]; 436 | z_axis->y = m[2][1]; 437 | z_axis->z = m[2][2]; 438 | } 439 | 440 | void matrix4x4_init_orthographic(matrix4x4 m, float left, float right, float bottom, float top, float near, float far) 441 | { 442 | m[0][0] = 2.0f / (right - left); 443 | m[0][1] = 0.0f; 444 | m[0][2] = 0.0f; 445 | m[0][3] = -(right + left) / (right - left); 446 | 447 | m[1][0] = 0.0f; 448 | m[1][1] = 2.0f / (top - bottom); 449 | m[1][2] = 0.0f; 450 | m[1][3] = -(top + bottom) / (top - bottom); 451 | 452 | m[2][0] = 0.0f; 453 | m[2][1] = 0.0f; 454 | m[2][2] = -2.0f / (far - near); 455 | m[2][3] = -(far + near) / (far - near); 456 | 457 | m[3][0] = 0.0f; 458 | m[3][1] = 0.0f; 459 | m[3][2] = 0.0f; 460 | m[3][3] = 1.0f; 461 | } 462 | 463 | void matrix4x4_init_frustum(matrix4x4 m, float left, float right, float bottom, float top, float near, float far) 464 | { 465 | m[0][0] = (2.0f * near) / (right - left); 466 | m[0][1] = 0.0f; 467 | m[0][2] = (right + left) / (right - left); 468 | m[0][3] = 0.0f; 469 | 470 | m[1][0] = 0.0f; 471 | m[1][1] = (2.0f * near) / (top - bottom); 472 | m[1][2] = (top + bottom) / (top - bottom); 473 | m[1][3] = 0.0f; 474 | 475 | m[2][0] = 0.0f; 476 | m[2][1] = 0.0f; 477 | m[2][2] = -(far + near) / (far - near); 478 | m[2][3] = (-2.0f * far * near) / (far - near); 479 | 480 | m[3][0] = 0.0f; 481 | m[3][1] = 0.0f; 482 | m[3][2] = -1.0f; 483 | m[3][3] = 0.0f; 484 | } 485 | 486 | void matrix4x4_init_perspective(matrix4x4 m, float fov, float aspect, float near, float far) 487 | { 488 | float half_height = near * tanf(DEG_TO_RAD(fov) * 0.5f); 489 | float half_width = half_height * aspect; 490 | 491 | matrix4x4_init_frustum(m, -half_width, half_width, -half_height, half_height, near, far); 492 | } 493 | 494 | void matrix3x3_normal_matrix(matrix3x3 out, const matrix4x4 m) 495 | { 496 | matrix4x4 m1, m2; 497 | 498 | matrix4x4_invert(m1, m); 499 | matrix4x4_transpose(m2, m1); 500 | matrix3x3_from_matrix4x4(out, m2); 501 | } 502 | 503 | void matrix4x4_build_model_matrix(matrix4x4 m, const vector3f *translation, 504 | const vector3f *rotation) 505 | { 506 | matrix4x4 mt, mrx, mry, mrz; 507 | matrix4x4 mtmp1, mtmp2; 508 | 509 | matrix4x4_init_translation_vector3f(mt, translation); 510 | matrix4x4_init_rotation_x(mrx, rotation->x); 511 | matrix4x4_init_rotation_y(mry, rotation->y); 512 | matrix4x4_init_rotation_z(mrz, rotation->z); 513 | 514 | matrix4x4_multiply(mtmp1, mrx, mry); 515 | matrix4x4_multiply(mtmp2, mrz, mtmp1); 516 | matrix4x4_multiply(m, mt, mtmp2); 517 | } 518 | 519 | // Code from http://aras-p.info/texts/obliqueortho.html 520 | // and http://www.terathon.com/code/oblique.php 521 | void matrix4x4_oblique_near_plane(matrix4x4 projection, const vector4f *clip_plane) 522 | { 523 | vector4f v; 524 | vector4f q; 525 | vector4f c; 526 | matrix4x4 proj_inv; 527 | 528 | vector4f_init(&v, sgn(clip_plane->x), sgn(clip_plane->y), 1.0f, 1.0f); 529 | 530 | matrix4x4_invert(proj_inv, projection); 531 | 532 | vector4f_matrix4x4_mult(&q, proj_inv, &v); 533 | 534 | vector4f_scalar_mult_dest(&c, clip_plane, 2.0f / vector4f_dot_product(clip_plane, &q)); 535 | 536 | // third row = clip plane - fourth row 537 | projection[2][0] = c.x - projection[3][0]; 538 | projection[2][1] = c.y - projection[3][1]; 539 | projection[2][2] = c.z - projection[3][2]; 540 | projection[2][3] = c.w - projection[3][3]; 541 | } 542 | --------------------------------------------------------------------------------