this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Added a first tier 3 implementation of GPU_BlitBatchAttributes() for sending (only) custom attributes to the shader program.

+468 -13
+185 -5
SDL_gpu/GL_common/SDL_gpu_GL_common.inl
··· 2997 2997 return 0; 2998 2998 } 2999 2999 3000 + 3001 + static int BlitBatchAttributes(GPU_Renderer* renderer, GPU_Image* src, GPU_Target* dest, unsigned int numSprites, unsigned int numAttributes, GPU_Attribute* attributes) 3002 + { 3003 + if(src == NULL || dest == NULL) 3004 + return -1; 3005 + if(renderer != src->renderer || renderer != dest->renderer) 3006 + return -2; 3007 + 3008 + // TODO: Implement this function for more renderers. 3009 + #ifndef SDL_GPU_USE_GL_TIER3 3010 + GPU_LogError("GPU_BlitBatchAttributes(): Not supported by this renderer.\n"); 3011 + return -4; 3012 + #endif 3013 + 3014 + makeContextCurrent(renderer, dest); 3015 + if(renderer->current_context_target == NULL) 3016 + return -3; 3017 + 3018 + // Bind the texture to which subsequent calls refer 3019 + bindTexture(renderer, src); 3020 + 3021 + // Bind the FBO 3022 + if(bindFramebuffer(renderer, dest)) 3023 + { 3024 + prepareToRenderToTarget(renderer, dest); 3025 + prepareToRenderImage(renderer, dest, src); 3026 + 3027 + glEnable(GL_TEXTURE_2D); 3028 + Uint8 isRTT = (dest->image != NULL); 3029 + 3030 + // Modify the viewport and projection matrix if rendering to a texture 3031 + GLint vp[4]; 3032 + if(isRTT) 3033 + { 3034 + glGetIntegerv(GL_VIEWPORT, vp); 3035 + 3036 + unsigned int w = dest->w; 3037 + unsigned int h = dest->h; 3038 + 3039 + glViewport( 0, 0, w, h); 3040 + 3041 + GPU_MatrixMode( GPU_PROJECTION ); 3042 + GPU_PushMatrix(); 3043 + GPU_LoadIdentity(); 3044 + 3045 + GPU_Ortho(0.0f, w, 0.0f, h, -1.0f, 1.0f); // Special inverted orthographic projection because tex coords are inverted already. 3046 + 3047 + GPU_MatrixMode( GPU_MODELVIEW ); 3048 + } 3049 + 3050 + setClipRect(renderer, dest); 3051 + 3052 + 3053 + CONTEXT_DATA* cdata = (CONTEXT_DATA*)renderer->current_context_target->context->data; 3054 + unsigned short* index_buffer = cdata->index_buffer; 3055 + 3056 + renderer->FlushBlitBuffer(renderer); 3057 + 3058 + #if defined(SDL_GPU_USE_GL_TIER3) 3059 + 3060 + 3061 + 3062 + TARGET_DATA* data = ((TARGET_DATA*)renderer->current_context_target->data); 3063 + 3064 + // Upload our modelviewprojection matrix 3065 + if(data->current_shader_block.modelViewProjection_loc >= 0) 3066 + { 3067 + float mvp[16]; 3068 + GPU_GetModelViewProjection(mvp); 3069 + glUniformMatrix4fv(data->current_shader_block.modelViewProjection_loc, 1, 0, mvp); 3070 + } 3071 + 3072 + // Update the vertex array object's buffers 3073 + #if !defined(SDL_GPU_USE_GLES) || SDL_GPU_GLES_MAJOR_VERSION != 2 3074 + glBindVertexArray(data->blit_VAO); 3075 + #endif 3076 + 3077 + // TODO: Move these into storage so we don't have to keep recreating them 3078 + GLuint buffers[16]; 3079 + glGenBuffers(16, buffers); 3080 + 3081 + int i; 3082 + for(i = 0; i < numAttributes; i++) 3083 + { 3084 + glBindBuffer(GL_ARRAY_BUFFER, buffers[i]); 3085 + 3086 + // Copy the whole buffer to the GPU 3087 + // FIXME: Identify which attributes are interleaved so we can just upload the array once. 3088 + glBufferData(GL_ARRAY_BUFFER, attributes[i].format.stride_bytes * (numSprites*4), attributes[i].values, GL_STREAM_DRAW); // Fills GPU buffer with data. 3089 + } 3090 + 3091 + // Only do so many at a time 3092 + int sprites_so_far = 0; 3093 + int partial_num_sprites = cdata->blit_buffer_max_num_vertices/4; 3094 + while(1) 3095 + { 3096 + if(numSprites < partial_num_sprites) 3097 + partial_num_sprites = numSprites; 3098 + if(partial_num_sprites <= 0) 3099 + break; 3100 + 3101 + // Triangle indices 3102 + for(i = 0; i < partial_num_sprites; i++) 3103 + { 3104 + int buffer_num_vertices = (sprites_so_far + i)*4; 3105 + // First tri 3106 + index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices; // 0 3107 + index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+1; // 1 3108 + index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+2; // 2 3109 + 3110 + // Second tri 3111 + index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices; // 0 3112 + index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+2; // 2 3113 + index_buffer[cdata->index_buffer_num_vertices++] = buffer_num_vertices+3; // 3 3114 + } 3115 + 3116 + // Upload attribute buffers 3117 + 3118 + for(i = 0; i < numAttributes; i++) 3119 + { 3120 + glBindBuffer(GL_ARRAY_BUFFER, buffers[i]); 3121 + 3122 + // Specify the formatting of the buffer 3123 + if(attributes[i].location >= 0) 3124 + { 3125 + glEnableVertexAttribArray(attributes[i].location); 3126 + if(!attributes[i].format.normalize && attributes[i].format.type != GPU_FLOAT && attributes[i].format.type != GPU_DOUBLE) 3127 + { 3128 + glVertexAttribIPointer(attributes[i].location, 3129 + attributes[i].format.num_elems_per_vertex, 3130 + attributes[i].format.type, 3131 + attributes[i].format.stride_bytes, 3132 + (void*)(attributes[i].format.offset_bytes)); 3133 + } 3134 + else 3135 + { 3136 + glVertexAttribPointer(attributes[i].location, 3137 + attributes[i].format.num_elems_per_vertex, 3138 + attributes[i].format.type, 3139 + attributes[i].format.normalize, 3140 + attributes[i].format.stride_bytes, 3141 + (void*)(attributes[i].format.offset_bytes)); 3142 + } 3143 + } 3144 + } 3145 + 3146 + glDrawElements(GL_TRIANGLES, cdata->index_buffer_num_vertices, GL_UNSIGNED_SHORT, cdata->index_buffer); 3147 + 3148 + sprites_so_far += partial_num_sprites; 3149 + numSprites -= partial_num_sprites; 3150 + 3151 + cdata->index_buffer_num_vertices = 0; 3152 + } 3153 + 3154 + glDeleteBuffers(16, buffers); 3155 + 3156 + #if !defined(SDL_GPU_USE_GLES) || SDL_GPU_GLES_MAJOR_VERSION != 2 3157 + glBindVertexArray(0); 3158 + #endif 3159 + 3160 + 3161 + #endif 3162 + 3163 + unsetClipRect(renderer, dest); 3164 + 3165 + // restore viewport and projection 3166 + if(isRTT) 3167 + { 3168 + glViewport(vp[0], vp[1], vp[2], vp[3]); 3169 + 3170 + GPU_MatrixMode( GPU_PROJECTION ); 3171 + GPU_PopMatrix(); 3172 + GPU_MatrixMode( GPU_MODELVIEW ); 3173 + } 3174 + } 3175 + 3176 + return 0; 3177 + } 3178 + 3000 3179 static float SetZ(GPU_Renderer* renderer, float z) 3001 3180 { 3002 3181 if(renderer == NULL) ··· 3611 3790 return shader_message; 3612 3791 } 3613 3792 3614 - static int GetAttribLocation(GPU_Renderer* renderer, Uint32 program_object, const char* attrib_name) 3793 + static int GetAttributeLocation(GPU_Renderer* renderer, Uint32 program_object, const char* attrib_name) 3615 3794 { 3616 3795 #ifndef SDL_GPU_DISABLE_SHADERS 3617 3796 return glGetAttribLocation(program_object, attrib_name); ··· 3636 3815 if(position_name == NULL) 3637 3816 b.position_loc = -1; 3638 3817 else 3639 - b.position_loc = renderer->GetAttribLocation(renderer, program_object, position_name); 3818 + b.position_loc = renderer->GetAttributeLocation(renderer, program_object, position_name); 3640 3819 3641 3820 if(texcoord_name == NULL) 3642 3821 b.texcoord_loc = -1; 3643 3822 else 3644 - b.texcoord_loc = renderer->GetAttribLocation(renderer, program_object, texcoord_name); 3823 + b.texcoord_loc = renderer->GetAttributeLocation(renderer, program_object, texcoord_name); 3645 3824 3646 3825 if(color_name == NULL) 3647 3826 b.color_loc = -1; 3648 3827 else 3649 - b.color_loc = renderer->GetAttribLocation(renderer, program_object, color_name); 3828 + b.color_loc = renderer->GetAttributeLocation(renderer, program_object, color_name); 3650 3829 3651 3830 if(modelViewMatrix_name == NULL) 3652 3831 b.modelViewProjection_loc = -1; ··· 3897 4076 renderer->BlitTransformX = &BlitTransformX; \ 3898 4077 renderer->BlitTransformMatrix = &BlitTransformMatrix; \ 3899 4078 renderer->BlitBatch = &BlitBatch; \ 4079 + renderer->BlitBatchAttributes = &BlitBatchAttributes; \ 3900 4080 \ 3901 4081 renderer->SetZ = &SetZ; \ 3902 4082 renderer->GetZ = &GetZ; \ ··· 3925 4105 renderer->ActivateShaderProgram = &ActivateShaderProgram; \ 3926 4106 renderer->DeactivateShaderProgram = &DeactivateShaderProgram; \ 3927 4107 renderer->GetShaderMessage = &GetShaderMessage; \ 3928 - renderer->GetAttribLocation = &GetAttribLocation; \ 4108 + renderer->GetAttributeLocation = &GetAttributeLocation; \ 3929 4109 renderer->GetUniformLocation = &GetUniformLocation; \ 3930 4110 renderer->LoadShaderBlock = &LoadShaderBlock; \ 3931 4111 renderer->SetShaderBlock = &SetShaderBlock; \
+24 -4
SDL_gpu/SDL_gpu.c
··· 587 587 Uint8 pass_colors = (flags & GPU_PASSTHROUGH_COLORS); 588 588 589 589 // Passthrough data is per-vertex. Non-passthrough is per-sprite. They can't interleave cleanly. 590 - if((flags & GPU_PASSTHROUGH_ALL) != GPU_PASSTHROUGH_ALL) 590 + if(flags & GPU_PASSTHROUGH_ALL && (flags & GPU_PASSTHROUGH_ALL) != GPU_PASSTHROUGH_ALL) 591 591 { 592 592 GPU_LogError("GPU_BlitBatch: Cannot interpret interleaved data using partial passthrough.\n"); 593 593 return -1; ··· 1120 1120 return result; 1121 1121 } 1122 1122 1123 + int GPU_BlitBatchAttributes(GPU_Image* src, GPU_Target* dest, unsigned int numSprites, unsigned int numAttributes, GPU_Attribute* attributes) 1124 + { 1125 + if(current_renderer == NULL || current_renderer->BlitBatchAttributes == NULL || numSprites == 0 || numAttributes == 0 || attributes == NULL) 1126 + return 0; 1127 + 1128 + return current_renderer->BlitBatchAttributes(current_renderer, src, dest, numSprites, numAttributes, attributes); 1129 + } 1130 + 1123 1131 1124 1132 float GPU_SetZ(float z) 1125 1133 { ··· 1467 1475 return current_renderer->GetShaderMessage(current_renderer); 1468 1476 } 1469 1477 1470 - int GPU_GetAttribLocation(Uint32 program_object, const char* attrib_name) 1478 + int GPU_GetAttributeLocation(Uint32 program_object, const char* attrib_name) 1471 1479 { 1472 - if(current_renderer == NULL || current_renderer->GetAttribLocation == NULL) 1480 + if(current_renderer == NULL || current_renderer->GetAttributeLocation == NULL) 1473 1481 return 0; 1474 1482 1475 - return current_renderer->GetAttribLocation(current_renderer, program_object, attrib_name); 1483 + return current_renderer->GetAttributeLocation(current_renderer, program_object, attrib_name); 1484 + } 1485 + 1486 + GPU_AttributeFormat GPU_MakeAttributeFormat(int num_elems_per_vertex, GPU_TypeEnum type, Uint8 normalize, int stride_bytes, int offset_bytes) 1487 + { 1488 + GPU_AttributeFormat f = {num_elems_per_vertex, type, normalize, stride_bytes, offset_bytes}; 1489 + return f; 1490 + } 1491 + 1492 + GPU_Attribute GPU_MakeAttribute(int location, void* values, GPU_AttributeFormat format) 1493 + { 1494 + GPU_Attribute a = {location, values, format}; 1495 + return a; 1476 1496 } 1477 1497 1478 1498 int GPU_GetUniformLocation(Uint32 program_object, const char* uniform_name)
+45 -1
SDL_gpu/SDL_gpu.h
··· 225 225 226 226 #define GPU_PASSTHROUGH_ALL (GPU_PASSTHROUGH_VERTICES | GPU_PASSTHROUGH_TEXCOORDS | GPU_PASSTHROUGH_COLORS) 227 227 228 + /*! Type enumeration for GPU_AttributeFormat specifications. */ 229 + typedef Uint32 GPU_TypeEnum; 230 + // Use OpenGL's values for simpler translation 231 + static const GPU_BlitFlagEnum GPU_BYTE = 0x1400; 232 + static const GPU_BlitFlagEnum GPU_UNSIGNED_BYTE = 0x1401; 233 + static const GPU_BlitFlagEnum GPU_SHORT = 0x1402; 234 + static const GPU_BlitFlagEnum GPU_UNSIGNED_SHORT = 0x1403; 235 + static const GPU_BlitFlagEnum GPU_INT = 0x1404; 236 + static const GPU_BlitFlagEnum GPU_UNSIGNED_INT = 0x1405; 237 + static const GPU_BlitFlagEnum GPU_FLOAT = 0x1406; 238 + static const GPU_BlitFlagEnum GPU_DOUBLE = 0x140A; 239 + 240 + 241 + typedef struct GPU_AttributeFormat 242 + { 243 + int num_elems_per_vertex; 244 + GPU_TypeEnum type; // GPU_FLOAT, GPU_INT, GPU_UNSIGNED_INT, etc. 245 + Uint8 normalize; 246 + int stride_bytes; // Number of bytes between two vertex specifications 247 + int offset_bytes; // Number of bytes to skip at the beginning of 'values' 248 + } GPU_AttributeFormat; 249 + 250 + typedef struct GPU_Attribute 251 + { 252 + int location; 253 + void* values; // Expect 4 values for each sprite 254 + GPU_AttributeFormat format; 255 + } GPU_Attribute; 256 + 257 + 228 258 229 259 /*! Renderer object which specializes the API to a particular backend. */ 230 260 struct GPU_Renderer ··· 330 360 /*! \see GPU_BlitBatch() */ 331 361 int (*BlitBatch)(GPU_Renderer* renderer, GPU_Image* src, GPU_Target* dest, unsigned int numSprites, float* values, GPU_BlitFlagEnum flags); 332 362 363 + /*! \see GPU_BlitBatchAttributes() */ 364 + int (*BlitBatchAttributes)(GPU_Renderer* renderer, GPU_Image* src, GPU_Target* dest, unsigned int numSprites, unsigned int numAttributes, GPU_Attribute* attributes); 365 + 333 366 /*! \see GPU_SetX() */ 334 367 float (*SetZ)(GPU_Renderer* renderer, float z); 335 368 ··· 398 431 const char* (*GetShaderMessage)(GPU_Renderer* renderer); 399 432 400 433 /*! \see GPU_GetAttribLocation() */ 401 - int (*GetAttribLocation)(GPU_Renderer* renderer, Uint32 program_object, const char* attrib_name); 434 + int (*GetAttributeLocation)(GPU_Renderer* renderer, Uint32 program_object, const char* attrib_name); 402 435 403 436 /*! \see GPU_GetUniformLocation() */ 404 437 int (*GetUniformLocation)(GPU_Renderer* renderer, Uint32 program_object, const char* uniform_name); ··· 722 755 */ 723 756 int GPU_BlitBatchSeparate(GPU_Image* src, GPU_Target* dest, unsigned int numSprites, float* positions, float* src_rects, float* colors, GPU_BlitFlagEnum flags); 724 757 758 + /*! Performs 'numSprites' blits of the 'src' image to the 'dest' target. 759 + * \param numAttributes Number of shader attributes to use 760 + * \param attributes Array of 'numAttributes' shader attribute specifiers 761 + */ 762 + int GPU_BlitBatchAttributes(GPU_Image* src, GPU_Target* dest, unsigned int numSprites, unsigned int numAttributes, GPU_Attribute* attributes); 725 763 726 764 /*! Sets the renderer's z-depth. 727 765 * \return The previous z-depth */ ··· 858 896 859 897 /*! Returns an integer representing the location of the specified attribute shader variable. */ 860 898 int GPU_GetAttributeLocation(Uint32 program_object, const char* attrib_name); 899 + 900 + /*! Returns a filled GPU_AttributeFormat object. */ 901 + GPU_AttributeFormat GPU_MakeAttributeFormat(int num_elems_per_vertex, GPU_TypeEnum type, Uint8 normalize, int stride_bytes, int offset_bytes); 902 + 903 + /*! Returns a filled GPU_Attribute object. */ 904 + GPU_Attribute GPU_MakeAttribute(int location, void* values, GPU_AttributeFormat format); 861 905 862 906 /*! Returns an integer representing the location of the specified uniform shader variable. */ 863 907 int GPU_GetUniformLocation(Uint32 program_object, const char* uniform_name);
+214 -3
demos/blit-batch/main.c
··· 4 4 5 5 int do_interleaved(GPU_Target* screen) 6 6 { 7 - 7 + GPU_LogError("do_interleaved()\n"); 8 8 GPU_Image* image = GPU_LoadImage("data/small_test.png"); 9 9 if(image == NULL) 10 10 return -1; ··· 140 140 141 141 int do_separate(GPU_Target* screen) 142 142 { 143 - 143 + GPU_LogError("do_separate()\n"); 144 144 GPU_Image* image = GPU_LoadImage("data/small_test.png"); 145 145 if(image == NULL) 146 146 return -1; ··· 188 188 else if(event.key.keysym.sym == SDLK_SPACE) 189 189 { 190 190 done = 1; 191 - return_value = 1; 191 + return_value = 3; 192 192 } 193 193 else if(event.key.keysym.sym == SDLK_EQUALS || event.key.keysym.sym == SDLK_PLUS) 194 194 { ··· 263 263 GPU_FreeImage(image); 264 264 265 265 return return_value; 266 + } 267 + 268 + 269 + int do_attributes(GPU_Target* screen) 270 + { 271 + GPU_LogError("do_attributes()\n"); 272 + GPU_Image* image = GPU_LoadImage("data/small_test.png"); 273 + if(image == NULL) 274 + return -1; 275 + 276 + int return_value = 0; 277 + 278 + float dt = 0.010f; 279 + 280 + Uint32 startTime = SDL_GetTicks(); 281 + long frameCount = 0; 282 + 283 + int maxSprites = 50000; 284 + int numSprites = 101; 285 + 286 + // 3 pos floats per vertex, 2 texcoords, 4 color components 287 + int floats_per_vertex = 3 + 2 + 4; 288 + int floats_per_sprite = floats_per_vertex*4; 289 + float* sprite_values = (float*)malloc(sizeof(float)*maxSprites*floats_per_sprite); 290 + 291 + // FIXME: Need a better way to be sure of which shader is current. 292 + GPU_Attribute attributes[3] = { 293 + GPU_MakeAttribute(GPU_GetAttributeLocation(screen->context->current_shader_program, "gpu_Vertex"), sprite_values, 294 + GPU_MakeAttributeFormat(3, GPU_FLOAT, 0, floats_per_vertex*sizeof(float), 0)), 295 + GPU_MakeAttribute(GPU_GetAttributeLocation(screen->context->current_shader_program, "gpu_TexCoord"), sprite_values, 296 + GPU_MakeAttributeFormat(2, GPU_FLOAT, 0, floats_per_vertex*sizeof(float), 3*sizeof(float))), 297 + GPU_MakeAttribute(GPU_GetAttributeLocation(screen->context->current_shader_program, "gpu_Color"), sprite_values, 298 + GPU_MakeAttributeFormat(4, GPU_FLOAT, 0, floats_per_vertex*sizeof(float), 5*sizeof(float))) 299 + }; 300 + 301 + float* velx = (float*)malloc(sizeof(float)*maxSprites); 302 + float* vely = (float*)malloc(sizeof(float)*maxSprites); 303 + int i; 304 + int val_n = 0; 305 + for(i = 0; i < maxSprites; i++) 306 + { 307 + float x = rand()%screen->w; 308 + float y = rand()%screen->h; 309 + sprite_values[val_n++] = x - image->w/2; 310 + sprite_values[val_n++] = y - image->h/2; 311 + sprite_values[val_n++] = 0; 312 + 313 + sprite_values[val_n++] = 0; 314 + sprite_values[val_n++] = 0; 315 + 316 + sprite_values[val_n++] = 1.0f; 317 + sprite_values[val_n++] = 1.0f; 318 + sprite_values[val_n++] = 1.0f; 319 + sprite_values[val_n++] = 1.0f; 320 + 321 + sprite_values[val_n++] = x + image->w/2; 322 + sprite_values[val_n++] = y - image->h/2; 323 + sprite_values[val_n++] = 0; 324 + 325 + sprite_values[val_n++] = 1; 326 + sprite_values[val_n++] = 0; 327 + 328 + sprite_values[val_n++] = 1.0f; 329 + sprite_values[val_n++] = 1.0f; 330 + sprite_values[val_n++] = 1.0f; 331 + sprite_values[val_n++] = 1.0f; 332 + 333 + sprite_values[val_n++] = x + image->w/2; 334 + sprite_values[val_n++] = y + image->h/2; 335 + sprite_values[val_n++] = 0; 336 + 337 + sprite_values[val_n++] = 1; 338 + sprite_values[val_n++] = 1; 339 + 340 + sprite_values[val_n++] = 1.0f; 341 + sprite_values[val_n++] = 1.0f; 342 + sprite_values[val_n++] = 1.0f; 343 + sprite_values[val_n++] = 1.0f; 344 + 345 + sprite_values[val_n++] = x - image->w/2; 346 + sprite_values[val_n++] = y + image->h/2; 347 + sprite_values[val_n++] = 0; 348 + 349 + sprite_values[val_n++] = 0; 350 + sprite_values[val_n++] = 1; 351 + 352 + sprite_values[val_n++] = 1.0f; 353 + sprite_values[val_n++] = 1.0f; 354 + sprite_values[val_n++] = 1.0f; 355 + sprite_values[val_n++] = 1.0f; 356 + 357 + velx[i] = 10 + rand()%screen->w/10; 358 + vely[i] = 10 + rand()%screen->h/10; 359 + if(rand()%2) 360 + velx[i] = -velx[i]; 361 + if(rand()%2) 362 + vely[i] = -vely[i]; 363 + } 364 + 365 + 366 + Uint8 done = 0; 367 + SDL_Event event; 368 + while(!done) 369 + { 370 + while(SDL_PollEvent(&event)) 371 + { 372 + if(event.type == SDL_QUIT) 373 + done = 1; 374 + else if(event.type == SDL_KEYDOWN) 375 + { 376 + if(event.key.keysym.sym == SDLK_ESCAPE) 377 + done = 1; 378 + else if(event.key.keysym.sym == SDLK_SPACE) 379 + { 380 + done = 1; 381 + return_value = 1; 382 + } 383 + else if(event.key.keysym.sym == SDLK_EQUALS || event.key.keysym.sym == SDLK_PLUS) 384 + { 385 + if(numSprites < maxSprites) 386 + numSprites += 100; 387 + GPU_LogError("Sprites: %d\n", numSprites); 388 + frameCount = 0; 389 + startTime = SDL_GetTicks(); 390 + } 391 + else if(event.key.keysym.sym == SDLK_MINUS) 392 + { 393 + if(numSprites > 1) 394 + numSprites -= 100; 395 + if(numSprites < 1) 396 + numSprites = 1; 397 + GPU_LogError("Sprites: %d\n", numSprites); 398 + frameCount = 0; 399 + startTime = SDL_GetTicks(); 400 + } 401 + } 402 + } 403 + 404 + GPU_Clear(screen); 405 + 406 + for(i = 0; i < numSprites; i++) 407 + { 408 + val_n = floats_per_sprite*i; 409 + float x = sprite_values[val_n] + image->w/2; 410 + float y = sprite_values[val_n+1] + image->h/2; 411 + 412 + x += velx[i]*dt; 413 + y += vely[i]*dt; 414 + if(x < 0) 415 + { 416 + x = 0; 417 + velx[i] = -velx[i]; 418 + } 419 + else if(x > screen->w) 420 + { 421 + x = screen->w; 422 + velx[i] = -velx[i]; 423 + } 424 + 425 + if(y < 0) 426 + { 427 + y = 0; 428 + vely[i] = -vely[i]; 429 + } 430 + else if(y > screen->h) 431 + { 432 + y = screen->h; 433 + vely[i] = -vely[i]; 434 + } 435 + 436 + sprite_values[val_n] = x - image->w/2; 437 + sprite_values[val_n+1] = y - image->h/2; 438 + sprite_values[val_n+2] = 0; 439 + val_n += floats_per_vertex; 440 + sprite_values[val_n] = x + image->w/2; 441 + sprite_values[val_n+1] = y - image->h/2; 442 + sprite_values[val_n+2] = 0; 443 + val_n += floats_per_vertex; 444 + sprite_values[val_n] = x + image->w/2; 445 + sprite_values[val_n+1] = y + image->h/2; 446 + sprite_values[val_n+2] = 0; 447 + val_n += floats_per_vertex; 448 + sprite_values[val_n] = x - image->w/2; 449 + sprite_values[val_n+1] = y + image->h/2; 450 + sprite_values[val_n+2] = 0; 451 + } 452 + 453 + GPU_BlitBatchAttributes(image, screen, numSprites, 3, attributes); 454 + 455 + GPU_Flip(screen); 456 + 457 + frameCount++; 458 + if(SDL_GetTicks() - startTime > 5000) 459 + { 460 + printf("Average FPS: %.2f\n", 1000.0f*frameCount/(SDL_GetTicks() - startTime)); 461 + frameCount = 0; 462 + startTime = SDL_GetTicks(); 463 + } 464 + } 465 + 466 + printf("Average FPS: %.2f\n", 1000.0f*frameCount/(SDL_GetTicks() - startTime)); 467 + 468 + free(sprite_values); 469 + free(velx); 470 + free(vely); 471 + 472 + GPU_FreeImage(image); 473 + 474 + return return_value; 266 475 } 267 476 268 477 int main(int argc, char* argv[]) ··· 282 491 i = do_interleaved(screen); 283 492 else if(i == 2) 284 493 i = do_separate(screen); 494 + else if(i == 3) 495 + i = do_attributes(screen); 285 496 else 286 497 i = 0; 287 498 }