diff --git a/src/core.c b/src/core.c index a2344395c..fbc4838a5 100644 --- a/src/core.c +++ b/src/core.c @@ -267,7 +267,6 @@ static bool cameraUseGravity = true; // Shaders variables static bool enabledPostpro = false; -static unsigned int fboShader = 0; //---------------------------------------------------------------------------------- // Other Modules Functions Declaration (required by core) @@ -327,7 +326,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition); // Initialize Window and Graphics Context (OpenGL) void InitWindow(int width, int height, const char *title) { - TraceLog(INFO, "Initializing raylib (v1.2.2)"); + TraceLog(INFO, "Initializing raylib (v1.3.0)"); // Store window title (could be useful...) windowTitle = title; @@ -366,7 +365,7 @@ void InitWindow(int width, int height, const char *title) // Android activity initialization void InitWindow(int width, int height, struct android_app *state) { - TraceLog(INFO, "Initializing raylib (v1.2.2)"); + TraceLog(INFO, "Initializing raylib (v1.3.0)"); app_dummy(); @@ -554,9 +553,8 @@ void BeginDrawing(void) void EndDrawing(void) { rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) - - // TODO: Set postprocessing shader to be passed: SetPostproShader()? - if (enabledPostpro) rlglDrawPostpro(fboShader); // Draw postprocessing effect (shader) + + if (enabledPostpro) rlglDrawPostpro(); // Draw postprocessing effect (shader) SwapBuffers(); // Copy back buffer to front buffer PollInputEvents(); // Poll user events @@ -604,7 +602,7 @@ void Begin3dMode(Camera camera) // Setup Camera view if (cameraMode == CAMERA_CUSTOM) currentCamera = camera; else currentCamera = internalCamera; - + Matrix view = MatrixLookAt(currentCamera.position, currentCamera.target, currentCamera.up); rlMultMatrixf(GetMatrixVector(view)); // Multiply MODELVIEW matrix by view matrix (camera) } @@ -707,54 +705,54 @@ void ShowLogo(void) Ray GetMouseRay(Vector2 mousePosition, Camera camera) { Ray ray; - + Matrix proj = MatrixIdentity(); Matrix view = MatrixLookAt(currentCamera.position, currentCamera.target, currentCamera.up); - + float aspect = (GLfloat)GetScreenWidth()/(GLfloat)GetScreenHeight(); double top = 0.1f*tanf(45.0f*PI / 360.0f); double right = top*aspect; - + proj = MatrixFrustum(-right, right, -top, top, 0.01f, 1000.0f); MatrixTranspose(&proj); float realy = (float)GetScreenHeight() - mousePosition.y; - + float z; // glReadPixels(mousePosition.x, mousePosition.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z); //http://www.bfilipek.com/2012/06/select-mouse-opengl.html Vector3 nearPoint = { mousePosition.x, realy, 0.0f }; Vector3 farPoint = { mousePosition.x, realy, 1.0f }; - + nearPoint = internalCamera.position; farPoint = rlglUnproject(farPoint, proj, view); - + Vector3 direction = VectorSubtract(farPoint, nearPoint); VectorNormalize(&direction); - - ray.position = nearPoint; + + ray.position = nearPoint; ray.direction = direction; - + // Test Vector2 screenPos; screenPos.x = (mousePosition.x / (float)GetScreenWidth() * 2.0) - 1.0f; screenPos.y = (mousePosition.y / (float)GetScreenHeight() * 2.0) - 1.0f; - + direction = VectorSubtract(internalCamera.target, internalCamera.position); - + printf("/nScreenPos %f, %f", screenPos.x, screenPos.y); - + Matrix rotate; rotate = MatrixIdentity(); rotate = MatrixRotate(0, 45*DEG2RAD*screenPos.y, 0); VectorTransform(&direction, rotate); - + VectorNormalize(&direction); - - ray.position = internalCamera.position; + + ray.position = internalCamera.position; ray.direction = direction; - + return ray; } @@ -790,7 +788,7 @@ void SetCameraMode(int mode) internalCamera.target = (Vector3){ 3, 0, 3}; ProcessCamera(&internalCamera, &internalCamera.position); } - + cameraMode = mode; } @@ -798,7 +796,7 @@ Camera UpdateCamera(Vector3 *position) { // Calculate camera if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, position); - + return internalCamera; } @@ -1114,16 +1112,23 @@ Vector2 GetTouchPosition(void) }*/ #endif -void InitPostShader(void) +// Set postprocessing shader +void SetPostproShader(Shader shader) { - rlglInitPostpro(); - - enabledPostpro = true; -} - -void SetPostShader(unsigned int shader) -{ - fboShader = shader; + if (rlGetVersion() == OPENGL_11) TraceLog(WARNING, "Postprocessing shaders not supported on OpenGL 1.1"); + else + { + if (!enabledPostpro) + { + enabledPostpro = true; + rlglInitPostpro(); + rlglSetPostproShader(shader); + } + else + { + rlglSetPostproShader(shader); + } + } } //---------------------------------------------------------------------------------- @@ -1894,7 +1899,7 @@ static void PollInputEvents(void) previousMouseWheelY = currentMouseWheelY; currentMouseWheelY = 0; - + glfwPollEvents(); // Register keyboard/mouse events... and window events! #elif defined(PLATFORM_ANDROID) @@ -2412,7 +2417,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x; cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y; } - + cameraMousePosition = GetMousePosition(); // Support for multiple automatic camera modes @@ -2422,12 +2427,12 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) { // Pass to orbiting camera if (IsKeyPressed('O')) cameraMode = CAMERA_ORBITAL; - + // Camera zoom if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0)) { cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY); - + if (cameraTargetDistance > FREE_CAMERA_DISTANCE_MAX_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MAX_CLAMP; } // Camera looking down @@ -2442,7 +2447,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance; camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance; camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance; - + if (camera->target.y < 0) camera->target.y = -0.001; } else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (GetMouseWheelMove() > 0)) @@ -2462,7 +2467,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance; camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance; camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance; - + if (camera->target.y > 0) camera->target.y = 0.001; } else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (GetMouseWheelMove() > 0)) @@ -2470,8 +2475,8 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY); if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP; } - - + + // Inputs if (IsKeyDown(KEY_LEFT_ALT)) { @@ -2487,7 +2492,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) // Get the mouse sensitivity cameraAngle.x += cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY; cameraAngle.y += cameraMouseVariation.y * -FREE_CAMERA_MOUSE_SENSITIVITY; - + // Angle clamp if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP * DEG2RAD; else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP * DEG2RAD; @@ -2500,55 +2505,55 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) camera->target.y += ((cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER); camera->target.z += ((cameraMouseVariation.x * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER); } - + // Focus to center if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 }; - + // Camera position update camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x; - + if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y; else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y; camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z; - + } break; case CAMERA_ORBITAL: { // Pass to free camera if (IsKeyPressed('O')) cameraMode = CAMERA_FREE; - + cameraAngle.x += ORBITAL_CAMERA_SPEED; - + // Camera zoom - cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY); + cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY); // Camera distance clamp if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP; - + // Focus to center if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 }; - + // Camera position update camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x; - + if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y; else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y; camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z; - + } break; case CAMERA_FIRST_PERSON: case CAMERA_THIRD_PERSON: { bool isMoving = false; - + // Keyboard inputs if (IsKeyDown('W')) { playerPosition->x -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; playerPosition->z -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER; - + isMoving = true; } else if (IsKeyDown('S')) @@ -2556,25 +2561,25 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) playerPosition->x += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; playerPosition->z += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER; - + isMoving = true; } - + if (IsKeyDown('A')) { playerPosition->x -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; playerPosition->z += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; - + isMoving = true; } else if (IsKeyDown('D')) { playerPosition->x += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; playerPosition->z -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER; - + isMoving = true; } - + if (IsKeyDown('E')) { if (!cameraUseGravity) playerPosition->y += 1 / PLAYER_MOVEMENT_DIVIDER; @@ -2583,32 +2588,32 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) { if (!cameraUseGravity) playerPosition->y -= 1 / PLAYER_MOVEMENT_DIVIDER; } - + if (cameraMode == CAMERA_THIRD_PERSON) { // Camera orientation calculation // Get the mouse sensitivity cameraAngle.x += cameraMouseVariation.x * -THIRD_PERSON_MOUSE_SENSITIVITY; cameraAngle.y += cameraMouseVariation.y * -THIRD_PERSON_MOUSE_SENSITIVITY; - + // Angle clamp if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP * DEG2RAD; else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP * DEG2RAD; - + // Camera zoom - cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY); - + cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY); + // Camera distance clamp if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP; - + // Camera is always looking at player camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x * cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x); camera->target.y = playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y; camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x * sin(cameraAngle.x); - + // Camera position update camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x; - + if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y; else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y; @@ -2617,25 +2622,25 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) else { if (isMoving) cameraMovementCounter++; - + // Camera orientation calculation // Get the mouse sensitivity cameraAngle.x += cameraMouseVariation.x * -FIRST_PERSON_MOUSE_SENSITIVITY; cameraAngle.y += cameraMouseVariation.y * -FIRST_PERSON_MOUSE_SENSITIVITY; - + // Angle clamp if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP * DEG2RAD; else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP * DEG2RAD; - + // Camera is always looking at player camera->target.x = camera->position.x - sin(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE; camera->target.y = camera->position.y + sin(cameraAngle.y) * FIRST_PERSON_FOCUS_DISTANCE; camera->target.z = camera->position.z - cos(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE; - + camera->position.x = playerPosition->x; camera->position.y = (playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMovementCounter / FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER) / FIRST_PERSON_STEP_DIVIDER; camera->position.z = playerPosition->z; - + camera->up.x = sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER; camera->up.z = -sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER; } diff --git a/src/models.c b/src/models.c index 771d25a41..f4f83fd81 100644 --- a/src/models.c +++ b/src/models.c @@ -324,7 +324,7 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col rlPushMatrix(); rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(radius, radius, radius); - + rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -444,48 +444,17 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl rlPopMatrix(); } -// Draw a quad -void DrawQuad(Vector3 vertices[4], Vector2 textcoords[4], Vector3 normals[4], Color colors[4]) -{ - rlBegin(RL_QUADS); - rlColor4ub(colors[0].r, colors[0].g, colors[0].b, colors[0].a); - rlNormal3f(normals[0].x, normals[0].y, normals[0].z); - rlTexCoord2f(textcoords[0].x, textcoords[0].y); - rlVertex3f(vertices[0].x, vertices[0].y, vertices[0].z); - - rlColor4ub(colors[1].r, colors[1].g, colors[1].b, colors[1].a); - rlNormal3f(normals[1].x, normals[1].y, normals[1].z); - rlTexCoord2f(textcoords[1].x, textcoords[1].y); - rlVertex3f(vertices[1].x, vertices[1].y, vertices[1].z); - - rlColor4ub(colors[2].r, colors[2].g, colors[2].b, colors[2].a); - rlNormal3f(normals[2].x, normals[2].y, normals[2].z); - rlTexCoord2f(textcoords[2].x, textcoords[2].y); - rlVertex3f(vertices[2].x, vertices[2].y, vertices[2].z); - - rlColor4ub(colors[3].r, colors[3].g, colors[3].b, colors[3].a); - rlNormal3f(normals[3].x, normals[3].y, normals[3].z); - rlTexCoord2f(textcoords[3].x, textcoords[3].y); - rlVertex3f(vertices[3].x, vertices[3].y, vertices[3].z); - rlEnd(); -} - // Draw a plane -void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color) +void DrawPlane(Vector3 centerPos, Vector2 size, Color color) { // NOTE: QUADS usage require defining a texture on OpenGL 3.3+ if (rlGetVersion() != OPENGL_11) rlEnableTexture(whiteTexture); // Default white texture - // NOTE: Plane is always created on XZ ground and then rotated + // NOTE: Plane is always created on XZ ground rlPushMatrix(); rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(size.x, 1.0f, size.y); - // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... - rlRotatef(rotation.x, 1, 0, 0); - rlRotatef(rotation.y, 0, 1, 0); - rlRotatef(rotation.z, 0, 0, 1); - rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); rlNormal3f(0.0f, 1.0f, 0.0f); @@ -499,57 +468,27 @@ void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color) if (rlGetVersion() != OPENGL_11) rlDisableTexture(); } -// Draw a plane with divisions -// TODO: Test this function -void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, int slicesZ, Color color) +// Draw a quad +void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color) { - float quadWidth = size.x / slicesX; - float quadLenght = size.y / slicesZ; + // TODO: Calculate normals from vertex position + + rlBegin(RL_QUADS); + rlColor4ub(color.r, color.g, color.b, color.a); + //rlNormal3f(0.0f, 0.0f, 0.0f); - float texPieceW = 1 / size.x; - float texPieceH = 1 / size.y; - - // NOTE: Plane is always created on XZ ground and then rotated - rlPushMatrix(); - rlTranslatef(-size.x / 2, 0.0f, -size.y / 2); - rlTranslatef(centerPos.x, centerPos.y, centerPos.z); - - // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... - rlRotatef(rotation.x, 1, 0, 0); - rlRotatef(rotation.y, 0, 1, 0); - rlRotatef(rotation.z, 0, 0, 1); - - rlBegin(RL_QUADS); - rlColor4ub(color.r, color.g, color.b, color.a); - rlNormal3f(0.0f, 1.0f, 0.0f); - - for (int z = 0; z < slicesZ; z++) - { - for (int x = 0; x < slicesX; x++) - { - // Draw the plane quad by quad (with textcoords) - rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH); - rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght); - - rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH); - rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght); - - rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH + texPieceH); - rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght + quadLenght); - - rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH + texPieceH); - rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght + quadLenght); - } - } - rlEnd(); - - rlPopMatrix(); + rlVertex3f(v1.x, v1.y, v1.z); + rlVertex3f(v2.x, v2.y, v2.z); + rlVertex3f(v3.x, v3.y, v3.z); + rlVertex3f(v4.x, v4.y, v4.z); + rlEnd(); } +// Draw a ray line void DrawRay(Ray ray, Color color) { float scale = 10000; - + rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a); @@ -615,76 +554,7 @@ void DrawGizmo(Vector3 position) rlPopMatrix(); } -void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale) -{ - // NOTE: RGB = XYZ - rlPushMatrix(); - rlTranslatef(position.x, position.y, position.z); - rlScalef(scale, scale, scale); - rlRotatef(rotation.y, 0, 1, 0); - - rlBegin(RL_LINES); - // X Axis - rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x, position.y, position.z); - rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + 1, position.y, position.z); - - // ArrowX - rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + 1.1, position.y, position.z); - rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + .9, position.y, position.z + .1); - - rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + 1.1, position.y, position.z); - rlColor4ub(200, 0, 0, 255); rlVertex3f(position.x + .9, position.y, position.z - .1); - - // Y Axis - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y, position.z); - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y + 1, position.z); - - // ArrowY - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y + 1.1, position.z); - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + .1, position.y + .9, position.z); - - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x, position.y + 1.1, position.z); - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x - .1, position.y + .9, position.z); - - // Z Axis - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z); - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z - 1); - - // ArrowZ - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z - 1.1); - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + .1, position.y, position.z - .9); - - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x, position.y, position.z - 1.1); - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x - .1, position.y, position.z - .9); - - // Extra - int n = 3; - - // X Axis - for (int i=0; i < 360; i += 6) - { - rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*i) * scale/n, position.y + cos(DEG2RAD*i) * scale/n); - rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*(i+6)) * scale/n, position.y + cos(DEG2RAD*(i+6)) * scale/n); - } - - // Y Axis - for (int i=0; i < 360; i += 6) - { - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*i) * scale/n, 0, position.y + cos(DEG2RAD*i) * scale/n); - rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*(i+6)) * scale/n, 0, position.y + cos(DEG2RAD*(i+6)) * scale/n); - } - - // Z Axis - for (int i=0; i < 360; i += 6) - { - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + sin(DEG2RAD*i) * scale/n, position.y + cos(DEG2RAD*i) * scale/n, 0); - rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + sin(DEG2RAD*(i+6)) * scale/n, position.y + cos(DEG2RAD*(i+6)) * scale/n, 0); - } - rlEnd(); - rlPopMatrix(); -} - -// Load a 3d model +// Load a 3d model (from file) Model LoadModel(const char *fileName) { VertexData vData; @@ -694,6 +564,7 @@ Model LoadModel(const char *fileName) // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct + // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() Model model = rlglLoadModel(vData); // Upload vertex data to GPU // Now that vertex data is uploaded to GPU, we can free arrays @@ -708,6 +579,19 @@ Model LoadModel(const char *fileName) return model; } +// Load a 3d model (from vertex data) +Model LoadModelEx(VertexData data) +{ + Model model; + + // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() + model = rlglLoadModel(data); // Upload vertex data to GPU + + // NOTE: Vertex data is managed externally, must be deallocated manually + + return model; +} + // Load a heightmap image as a 3d model Model LoadHeightmap(Image heightmap, float maxHeight) { @@ -847,12 +731,12 @@ Model LoadCubicmap(Image cubesmap) float w = mapCubeSide; float h = mapCubeSide; - float h2 = mapCubeSide * 1.5; // TODO: Review walls height... + float h2 = mapCubeSide * 1.5; // TODO: Review walls height... Vector3 *mapVertices = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3)); Vector2 *mapTexcoords = (Vector2 *)malloc(maxTriangles * 3 * sizeof(Vector2)); Vector3 *mapNormals = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3)); - + // Define the 6 normals of the cube, we will combine them accordingly later... Vector3 n1 = { 1.0f, 0.0f, 0.0f }; Vector3 n2 = { -1.0f, 0.0f, 0.0f }; @@ -868,14 +752,14 @@ Model LoadCubicmap(Image cubesmap) float width; float height; } RectangleF; - + RectangleF rightTexUV = { 0, 0, 0.5, 0.5 }; RectangleF leftTexUV = { 0.5, 0, 0.5, 0.5 }; RectangleF frontTexUV = { 0, 0, 0.5, 0.5 }; RectangleF backTexUV = { 0.5, 0, 0.5, 0.5 }; RectangleF topTexUV = { 0, 0.5, 0.5, 0.5 }; RectangleF bottomTexUV = { 0.5, 0.5, 0.5, 0.5 }; - + for (int z = 0; z < mapHeight; z += mapCubeSide) { for (int x = 0; x < mapWidth; x += mapCubeSide) @@ -1105,7 +989,7 @@ Model LoadCubicmap(Image cubesmap) mapTexcoords[tcCounter + 4] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y }; mapTexcoords[tcCounter + 5] = (Vector2){ topTexUV.x + topTexUV.width, topTexUV.y + topTexUV.height }; tcCounter += 6; - + // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8) mapVertices[vCounter] = v6; mapVertices[vCounter + 1] = v7; @@ -1208,11 +1092,11 @@ void UnloadModel(Model model) free(model.mesh.normals); } - rlDeleteBuffers(model.vboId[0]); - rlDeleteBuffers(model.vboId[1]); - rlDeleteBuffers(model.vboId[2]); + rlDeleteBuffers(model.mesh.vboId[0]); + rlDeleteBuffers(model.mesh.vboId[1]); + rlDeleteBuffers(model.mesh.vboId[2]); - rlDeleteVertexArrays(model.vaoId); + rlDeleteVertexArrays(model.mesh.vaoId); rlDeleteTextures(model.texture.id); rlDeleteShader(model.shader.id); } @@ -1227,17 +1111,15 @@ void SetModelTexture(Model *model, Texture2D texture) void DrawModel(Model model, Vector3 position, float scale, Color tint) { Vector3 vScale = { scale, scale, scale }; - float rotAngle = 0.0f; - Vector3 rotAxis = { 0, 0, 0 }; + Vector3 rotationAxis = { 0, 0, 0 }; - rlglDrawModel(model, position, rotAngle, rotAxis, vScale, tint, false); + DrawModelEx(model, position, 0.0f, rotationAxis, vScale, tint); } // Draw a model with extended parameters void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint) { // NOTE: Rotation must be provided in degrees, it's converted to radians inside rlglDrawModel() - rlglDrawModel(model, position, rotationAngle, rotationAxis, scale, tint, false); } @@ -1245,10 +1127,9 @@ void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rot void DrawModelWires(Model model, Vector3 position, float scale, Color color) { Vector3 vScale = { scale, scale, scale }; - float rotAngle = 0.0f; - Vector3 rotAxis = { 0, 0, 0 }; + Vector3 rotationAxis = { 0, 0, 0 }; - rlglDrawModel(model, position, rotAngle, rotAxis, vScale, color, true); + rlglDrawModel(model, position, 0.0f, rotationAxis, vScale, color, true); } // Draw a billboard @@ -1360,7 +1241,7 @@ bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, floa float distance = sqrt(dx*dx + dy*dy + dz*dz); // Distance between centers if (distance <= (radiusA + radiusB)) collision = true; - + return collision; } @@ -1379,9 +1260,9 @@ bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, V bounds = new BoundingBox(minVertex, maxVertex); */ - + bool collision = true; - + if ((maxBBox1.x >= minBBox2.x) && (minBBox1.x <= maxBBox2.x)) { if ((maxBBox1.y < minBBox2.y) || (minBBox1.y > maxBBox2.y)) collision = false; @@ -1395,7 +1276,7 @@ bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, V bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere) { bool collision = false; - + if ((centerSphere.x - minBBox.x > radiusSphere) && (centerSphere.y - minBBox.y > radiusSphere) && (centerSphere.z - minBBox.z > radiusSphere) && (maxBBox.x - centerSphere.x > radiusSphere) && (maxBBox.y - centerSphere.y > radiusSphere) && (maxBBox.z - centerSphere.z > radiusSphere)) { @@ -1435,20 +1316,20 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p { // Detect the cell where the player is located Vector3 impactDirection = { 0, 0, 0 }; - + int locationCellX = 0; int locationCellY = 0; - + locationCellX = floor(playerPosition->x + mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE); locationCellY = floor(playerPosition->z + mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE); - + // Multiple Axis -------------------------------------------------------------------------------------------- - + // Axis x-, y- if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) && (cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) { playerPosition->x = locationCellX - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); @@ -1456,12 +1337,12 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p impactDirection = (Vector3) { 1, 0, 1}; } } - + // Axis x-, y+ if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) && (cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) { playerPosition->x = locationCellX - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); @@ -1469,12 +1350,12 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p impactDirection = (Vector3) { 1, 0, 1}; } } - + // Axis x+, y- if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) && (cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) { playerPosition->x = locationCellX + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); @@ -1482,12 +1363,12 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p impactDirection = (Vector3) { 1, 0, 1}; } } - + // Axis x+, y+ if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) && (cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) { playerPosition->x = locationCellX + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); @@ -1495,9 +1376,9 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p impactDirection = (Vector3) { 1, 0, 1}; } } - + // Single Axis --------------------------------------------------------------------------------------------------- - + // Axis x- if (cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) { @@ -1534,89 +1415,89 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p impactDirection = (Vector3) { 0, 0, 1}; } } - + // Diagonals ------------------------------------------------------------------------------------------------------- - + // Axis x-, y- if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) && (cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) && (cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX - 1)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) { if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) > ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY)) playerPosition->x = locationCellX - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); else playerPosition->z = locationCellY - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - + // Return ricochet - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius / 3)) { impactDirection = (Vector3) { 1, 0, 1}; } } } - + // Axis x-, y+ if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) && (cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) && (cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX - 1)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) { if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) > (1 - ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY))) playerPosition->x = locationCellX - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); else playerPosition->z = locationCellY + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - + // Return ricochet - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius / 3)) { impactDirection = (Vector3) { 1, 0, 1}; } } } - + // Axis x+, y- if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) && (cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) && (cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX + 1)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) { if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) < (1 - ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY))) playerPosition->x = locationCellX + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); else playerPosition->z = locationCellY - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - + // Return ricochet - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius / 3)) { impactDirection = (Vector3) { 1, 0, 1}; } } } - + // Axis x+, y+ if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) && (cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) && (cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX + 1)].r != 0)) { - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) { if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) < ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY)) playerPosition->x = locationCellX + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); else playerPosition->z = locationCellY + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - + // Return ricochet - if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && + if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius / 3)) { impactDirection = (Vector3) { 1, 0, 1}; } } } - + // Floor collision if (playerPosition->y <= radius) { @@ -1629,7 +1510,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p playerPosition->y = (1.5 - radius) - 0.01; impactDirection = (Vector3) { impactDirection.x, 1, impactDirection.z}; } - + return impactDirection; } diff --git a/src/raylib.h b/src/raylib.h index c6c3e32a4..0e532ebee 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib 1.2 (www.raylib.com) +* raylib 1.3.0 (www.raylib.com) * * A simple and easy-to-use library to learn videogames programming * @@ -199,6 +199,14 @@ typedef struct Vector3 { float z; } Vector3; +// Matrix type (OpenGL style 4x4 - right handed, column major) +typedef struct Matrix { + float m0, m4, m8, m12; + float m1, m5, m9, m13; + float m2, m6, m10, m14; + float m3, m7, m11, m15; +} Matrix; + // Color type, RGBA (32bit) typedef struct Color { unsigned char r; @@ -258,24 +266,27 @@ typedef struct Camera { typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; // Vertex data definning a mesh +// NOTE: If using OpenGL 1.1, data loaded in CPU; if OpenGL 3.3+ data loaded in GPU (vaoId) typedef struct VertexData { int vertexCount; float *vertices; // 3 components per vertex float *texcoords; // 2 components per vertex float *normals; // 3 components per vertex unsigned char *colors; // 4 components per vertex + unsigned int vaoId; + unsigned int vboId[4]; } VertexData; // Shader type typedef struct Shader { unsigned int id; // Shader program id - + // Variable attributes unsigned int vertexLoc; // Vertex attribute location point (vertex shader) unsigned int texcoordLoc; // Texcoord attribute location point (vertex shader) unsigned int normalLoc; // Normal attribute location point (vertex shader) unsigned int colorLoc; // Color attibute location point (vertex shader) - + // Uniforms unsigned int projectionLoc; // Projection matrix uniform location point (vertex shader) unsigned int modelviewLoc; // ModeView matrix uniform location point (vertex shader) @@ -284,14 +295,11 @@ typedef struct Shader { } Shader; // 3d Model type -// NOTE: If using OpenGL 1.1, loaded in CPU (mesh); if OpenGL 3.3+ loaded in GPU (vaoId) typedef struct Model { VertexData mesh; - unsigned int vaoId; - unsigned int vboId[4]; + Matrix transform; Texture2D texture; Shader shader; - //Matrix transform; } Model; // Ray type (useful for raycast) @@ -315,6 +323,24 @@ typedef struct Wave { short channels; } Wave; +// Texture formats (support depends on OpenGL version) +typedef enum { + UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) + UNCOMPRESSED_R5G6B5, // 16 bpp + UNCOMPRESSED_R8G8B8, // 24 bpp + UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) + UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) + UNCOMPRESSED_R8G8B8A8, // 32 bpp + COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) + COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) + COMPRESSED_DXT3_RGBA, // 8 bpp + COMPRESSED_DXT5_RGBA, // 8 bpp + COMPRESSED_ETC1_RGB, // 4 bpp + COMPRESSED_ETC2_RGB, // 4 bpp + COMPRESSED_ETC2_EAC_RGBA, // 8 bpp + /*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp +} TextureFormat; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -366,8 +392,7 @@ Camera UpdateCamera(Vector3 *position); // Update camera wit void SetConfigFlags(char flags); // Enable some window configurations void ShowLogo(void); // Activates raylib logo at startup (can be done with flags) -void InitPostShader(void); // Initialize fullscreen postproduction shaders system -void SetPostShader(unsigned int shader); // Set fullscreen postproduction shader +void SetPostproShader(Shader shader); // Set fullscreen postproduction shader Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Gives the rayTrace from mouse position @@ -448,6 +473,7 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 Image LoadImage(const char *fileName); // Load an image into CPU memory (RAM) Image LoadImageFromRES(const char *rresName, int resId); // Load an image from rRES file (raylib Resource) Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory +Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps); // Load a texture from raw data into GPU memory Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource) Texture2D LoadTextureFromImage(Image image, bool genMipmaps); // Load a texture from image data (and generate mipmaps) Texture2D CreateTexture(Image image, bool genMipmaps); // [DEPRECATED] Same as LoadTextureFromImage() @@ -490,19 +516,18 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires -void DrawQuad(Vector3 vertices[4], Vector2 textcoords[4], Vector3 normals[4], Color colors[4]); // Draw a quad -void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color); // Draw a plane -void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, int slicesZ, Color color); // Draw a plane with divisions -void DrawRay(Ray ray, Color color); +void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ +void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color); // Draw a quad +void DrawRay(Ray ray, Color color); // Draw a ray line void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) void DrawGizmo(Vector3 position); // Draw simple gizmo -void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale); // Draw gizmo with extended parameters //DrawTorus(), DrawTeapot() are useless... //------------------------------------------------------------------------------------ // Model 3d Loading and Drawing Functions (Module: models) //------------------------------------------------------------------------------------ Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) +Model LoadModelEx(VertexData data); // Load a 3d model (from vertex data) //Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource) Model LoadHeightmap(Image heightmap, float maxHeight); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) @@ -517,7 +542,7 @@ void DrawModelWires(Model model, Vector3 position, float scale, Color color); void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec -Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader (vertex shader + fragment shader) +Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader (vertex shader + fragment shader) bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2); diff --git a/src/raymath.h b/src/raymath.h index b3676ed9b..133e18811 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -53,15 +53,15 @@ float y; float z; } Vector3; -#endif -// Matrix type (OpenGL style 4x4 - right handed, column major) -typedef struct Matrix { - float m0, m4, m8, m12; - float m1, m5, m9, m13; - float m2, m6, m10, m14; - float m3, m7, m11, m15; -} Matrix; + // Matrix type (OpenGL style 4x4 - right handed, column major) + typedef struct Matrix { + float m0, m4, m8, m12; + float m1, m5, m9, m13; + float m2, m6, m10, m14; + float m3, m7, m11, m15; + } Matrix; +#endif // Quaternion type typedef struct Quaternion { diff --git a/src/rlgl.c b/src/rlgl.c index 7d947d662..c4deda8f5 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -63,6 +63,28 @@ #define TEMP_VERTEX_BUFFER_SIZE 4096 // Temporal Vertex Buffer (required for vertex-transformations) // NOTE: Every vertex are 3 floats (12 bytes) +#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT + #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#endif +#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#endif +#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#endif +#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif +#ifndef GL_ETC1_RGB8_OES + #define GL_ETC1_RGB8_OES 0x8D64 +#endif +#ifndef GL_COMPRESSED_RGB8_ETC2 + #define GL_COMPRESSED_RGB8_ETC2 0x9274 +#endif +#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC + #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#endif + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -174,7 +196,8 @@ static bool useTempBuffer = false; static bool vaoSupported = false; // Framebuffer object and texture -static GLuint fbo, fboColorTexture, fboDepthTexture, fboShader = 0; +static GLuint fbo, fboColorTexture, fboDepthTexture; +static Model postproQuad; #endif #if defined(GRAPHICS_API_OPENGL_ES2) @@ -199,6 +222,7 @@ static Shader LoadSimpleShader(void); static void InitializeBuffers(void); static void InitializeBuffersGPU(void); static void UpdateBuffers(void); +static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat); // Custom shader files loading (external) static char *TextFileRead(char *fn); @@ -688,18 +712,21 @@ void rlDeleteTextures(unsigned int id) glDeleteTextures(1, &id); } +// Enable rendering to postprocessing FBO +void rlEnableFBO(void) +{ #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glBindFramebuffer(GL_FRAMEBUFFER, fbo); +#endif +} + // Unload shader from GPU memory void rlDeleteShader(unsigned int id) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glDeleteProgram(id); -} - -void rlEnableFBO(void) -{ - glBindFramebuffer(GL_FRAMEBUFFER, fbo); -} #endif +} // Unload vertex data (VAO) from GPU memory void rlDeleteVertexArrays(unsigned int id) @@ -840,7 +867,18 @@ void rlglInit(void) TraceLog(INFO, "Supported extension: %s", extensions); #endif */ +/* + GLint numComp = 0; + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numComp); + + GLint format[32] = { 0 }; + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, format); + for (int i = 0; i < numComp; i++) + { + TraceLog(INFO, "Supported compressed format: 0x%x", format[i]); + } +*/ #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Set default draw mode currentDrawMode = RL_TRIANGLES; @@ -869,7 +907,7 @@ void rlglInit(void) // Create default white texture for plain colors (required by shader) unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) - whiteTexture = rlglLoadTexture(pixels, 1, 1, R8G8B8A8, false); + whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1, false); if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); else TraceLog(WARNING, "Base white texture could not be loaded"); @@ -884,14 +922,14 @@ void rlglInit(void) } drawsCounter = 1; - draws[drawsCounter - 1].textureId = whiteTexture; + draws[drawsCounter - 1].textureId = whiteTexture; #endif } -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Init postpro system void rlglInitPostpro(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Create the texture that will serve as the color attachment for the framebuffer glGenTextures(1, &fboColorTexture); glBindTexture(GL_TEXTURE_2D, fboColorTexture); @@ -901,7 +939,7 @@ void rlglInitPostpro(void) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GetScreenWidth(), GetScreenHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); - + // Create the texture that will serve as the depth attachment for the framebuffer. glGenTextures(1, &fboDepthTexture); glBindTexture(GL_TEXTURE_2D, fboDepthTexture); @@ -921,17 +959,48 @@ void rlglInitPostpro(void) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fboDepthTexture, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - + if (status != GL_FRAMEBUFFER_COMPLETE) TraceLog(WARNING, "Framebuffer object could not be created..."); else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo); glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Create a simple quad model to render fbo texture + VertexData quadData; - fboShader = 0; + quadData.vertexCount = 6; - // TODO: Init simple quad VAO and data here? -} + float w = GetScreenWidth(); + float h = GetScreenHeight(); + + float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 }; + float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 }; + float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 }; + unsigned char quadColors[6*4] = { 255 }; + + quadData.vertices = quadPositions; + quadData.texcoords = quadTexcoords; + quadData.normals = quadNormals; + quadData.colors = quadColors; + + postproQuad = rlglLoadModel(quadData); + + Texture2D texture; + texture.id = fboColorTexture; + texture.width = w; + texture.height = h; + + SetModelTexture(&postproQuad, texture); #endif +} + +// Set postprocessing shader +void rlglSetPostproShader(Shader shader) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + SetModelShader(&postproQuad, shader); +#endif +} // Vertex Buffer Object deinitialization (memory free) void rlglClose(void) @@ -987,8 +1056,13 @@ void rlglClose(void) // Free GPU texture glDeleteTextures(1, &whiteTexture); - - if (fbo != 0) glDeleteFramebuffers(1, &fbo); + + if (fbo != 0) + { + glDeleteFramebuffers(1, &fbo); + + UnloadModel(postproQuad); + } free(draws); #endif @@ -1002,7 +1076,7 @@ void rlglDraw(void) if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) { glUseProgram(defaultShader.id); - + glUniformMatrix4fv(defaultShader.projectionLoc, 1, false, GetMatrixVector(projection)); glUniformMatrix4fv(defaultShader.modelviewLoc, 1, false, GetMatrixVector(modelview)); glUniform1i(defaultShader.textureLoc, 0); @@ -1142,68 +1216,15 @@ void rlglDraw(void) #endif } -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -void rlglDrawPostpro(unsigned int shaderId) +// Draw with postprocessing shader +void rlglDrawPostpro(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindFramebuffer(GL_FRAMEBUFFER, 0); - - // TODO: Draw screen quad with texture -/* - const float quadPositions[] = { 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 0.0, - -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0 }; - const float quadTexcoords[] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 }; - glBindBuffer(GL_ARRAY_BUFFER, quadVbo); - - glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), quadPositions); - glVertexAttribPointer(ATTRIB_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), quadTexcoords); - - glEnableVertexAttribArray(ATTRIB_VERTEX); - glEnableVertexAttribArray(ATTRIB_TEXCOORD0); - - glBindTexture(GL_TEXTURE_2D, fboColorTexture); - - glDrawArrays(GL_TRIANGLES, 0, 2*3); - - // Quad render using triangle strip - glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - glUseProgram(0); -*/ - rlEnableTexture(fboColorTexture); - - rlPushMatrix(); - rlBegin(RL_QUADS); - rlColor4ub(255, 255, 255, 255); - rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer - - // Bottom-left corner for texture and quad - rlTexCoord2f(0.0f, 1.0f); - rlVertex2f(0.0f, 0.0f); - - // Bottom-right corner for texture and quad - rlTexCoord2f(0.0f, 0.0f); - rlVertex2f(0.0f, GetScreenHeight()); - - // Top-right corner for texture and quad - rlTexCoord2f(1.0f, 0.0f); - rlVertex2f(GetScreenWidth(), GetScreenHeight()); - - // Top-left corner for texture and quad - rlTexCoord2f(1.0f, 1.0f); - rlVertex2f(GetScreenWidth(), 0.0f); - rlEnd(); - rlPopMatrix(); - - fboShader = shaderId; - - rlglDraw(); -} + rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, WHITE, false); #endif +} // Draw a 3d model void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires) @@ -1250,12 +1271,14 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glUseProgram(model.shader.id); - Vector3 rotation = { 0.0f, 0.0f, 0.0f }; + // TODO: Use model.transform matrix + + Vector3 rotation = { 0.0f, 0.0f, 0.0f }; // Get transform matrix (rotation -> scale -> translation) Matrix transform = MatrixTransform(position, rotation, scale); // Object-space transformation Matrix modelviewworld = MatrixMultiply(transform, modelview); // World-space transformation - + // Projection: Screen-space transformation // NOTE: Drawing in OpenGL 3.3+, transform is passed to shader @@ -1271,21 +1294,21 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r if (vaoSupported) { - glBindVertexArray(model.vaoId); + glBindVertexArray(model.mesh.vaoId); } else { // Bind model VBOs data - glBindBuffer(GL_ARRAY_BUFFER, model.vboId[0]); + glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[0]); glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(model.shader.vertexLoc); - glBindBuffer(GL_ARRAY_BUFFER, model.vboId[1]); + glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[1]); glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(model.shader.texcoordLoc); // Add normals support - glBindBuffer(GL_ARRAY_BUFFER, model.vboId[2]); + glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]); glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(model.shader.normalLoc); } @@ -1357,10 +1380,10 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height) // Get world coordinates from screen coordinates Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) -{ +{ //GLint viewport[4]; //glGetIntegerv(GL_VIEWPORT, viewport); - + // Viewport data int x = 0; int y = 0; @@ -1368,7 +1391,7 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) int height = GetScreenHeight(); float minDepth = 0.0f; float maxDepth = 1.0f; -/* +/* Matrix modelviewprojection = MatrixMultiply(modelview, projection); MatrixInvert(&modelviewprojection); @@ -1384,7 +1407,7 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) //if (!MathUtil.IsOne(a)) vector = (vector / a); //VectorScale(&vector, 1/a); - + return vector; */ /* @@ -1418,31 +1441,31 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) /* Quaternion quat; Vector3 vec; - + quat.x = 2.0f * GetMousePosition().x / (float)width - 1; quat.y = -(2.0f * GetMousePosition().y / (float)height - 1); quat.z = 0; quat.w = 1; - - Matrix invView; + + Matrix invView; MatrixInvert(&view); Matrix invProj; MatrixInvert(&proj); - + quat.x = invProj.m0 * quat.x + invProj.m4 * quat.y + invProj.m8 * quat.z + invProj.m12 * quat.w; quat.y = invProj.m1 * quat.x + invProj.m5 * quat.y + invProj.m9 * quat.z + invProj.m13 * quat.w; quat.z = invProj.m2 * quat.x + invProj.m6 * quat.y + invProj.m10 * quat.z + invProj.m14 * quat.w; quat.w = invProj.m3 * quat.x + invProj.m7 * quat.y + invProj.m11 * quat.z + invProj.m15 * quat.w; - + quat.x = invView.m0 * quat.x + invView.m4 * quat.y + invView.m8 * quat.z + invView.m12 * quat.w; quat.y = invView.m1 * quat.x + invView.m5 * quat.y + invView.m9 * quat.z + invView.m13 * quat.w; quat.z = invView.m2 * quat.x + invView.m6 * quat.y + invView.m10 * quat.z + invView.m14 * quat.w; quat.w = invView.m3 * quat.x + invView.m7 * quat.y + invView.m11 * quat.z + invView.m15 * quat.w; - + vec.x /= quat.w; vec.y /= quat.w; vec.z /= quat.w; - + return vec; */ /* @@ -1463,14 +1486,14 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) quat.y = ((source.y - (float)y)/(float)height*2.0) - 1.0f; quat.z = 2.0*source.z - 1.0; quat.w = 1.0; - + // Traspose quaternion and multiply Quaternion result; result.x = modelviewprojection.m0 * quad.x + modelviewprojection.m4 * quad.y + modelviewprojection.m8 * quad.z + modelviewprojection.m12 * quad.w; result.y = modelviewprojection.m1 * quad.x + modelviewprojection.m5 * quad.y + modelviewprojection.m9 * quad.z + modelviewprojection.m13 * quad.w; result.z = modelviewprojection.m2 * quad.x + modelviewprojection.m6 * quad.y + modelviewprojection.m10 * quad.z + modelviewprojection.m14 * quad.w; result.w = modelviewprojection.m3 * quad.x + modelviewprojection.m7 * quad.y + modelviewprojection.m11 * quad.z + modelviewprojection.m15 * quad.w; - + // Invert result.w = 1.0f / result.w; @@ -1488,47 +1511,65 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) Quaternion rayClip; Quaternion rayEye; Vector3 rayWorld; - + // Getting normal device coordinates float x = (2.0 * mousePosition.x) / GetScreenWidth() - 1.0; float y = 1.0 - (2.0 * mousePosition.y) / GetScreenHeight(); float z = 1.0; normalDeviceCoordinates = (Vector3){ x, y, z }; - + // Getting clip vector rayClip = (Quaternion){ normalDeviceCoordinates.x, normalDeviceCoordinates.y, -1, 1 }; - + Matrix invProjection = projection; MatrixInvert(&invProjection); - + rayEye = MatrixQuaternionMultiply(invProjection, rayClip); rayEye = (Quaternion){ rayEye.x, rayEye.y, -1, 0 }; - + Matrix invModelview = modelview; MatrixInvert(&invModelview); - + rayWorld = MatrixVector3Multiply(invModelview, (Vector3){rayEye.x, rayEye.y, rayEye.z} ); VectorNormalize(&rayWorld); - + return rayWorld; */ + return (Vector3){ 0, 0, 0 }; } // Convert image data to OpenGL texture (returns OpenGL valid Id) -unsigned int rlglLoadTexture(unsigned char *data, int width, int height, int colorMode, bool genMipmaps) +unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps) { - glBindTexture(GL_TEXTURE_2D,0); // Free any old binding + glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding GLuint id; - glGenTextures(1, &id); // Generate Pointer to the texture + + // TODO: Review compressed textures support by OpenGL version + /* (rlGetVersion() == OPENGL_11) + if ((textureFormat == COMPRESSED_DXT1_RGB) || (textureFormat == COMPRESSED_DXT3_RGBA) || (textureFormat == COMPRESSED_DXT5_RGBA) || + (textureFormat == COMPRESSED_ETC1_RGB8) || (textureFormat == COMPRESSED_ETC2_RGB8) || (textureFormat == COMPRESSED_ETC2_EAC_RGBA8)) + { + id = 0; + TraceLog(WARNING, "GPU compressed textures not supported on OpenGL 1.1"); + return id; + } + */ + + glGenTextures(1, &id); // Generate Pointer to the texture //glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, id); // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used! +#if defined(GRAPHICS_API_OPENGL_ES2) // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repead on x-axis - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repead on y-axis + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Set texture to clamp on x-axis + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set texture to clamp on y-axis +#else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis +#endif bool texIsPOT = false; @@ -1542,6 +1583,8 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, int col genMipmaps = false; } + // TODO: Support mipmaps --> if (mipmapCount > 1) + // If mipmaps are being used, we configure mag-min filters accordingly // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so only GL_LINEAR or GL_NEAREST can be used if (genMipmaps) @@ -1587,35 +1630,76 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, int col else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); #endif -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) // NOTE: We define internal (GPU) format as GL_RGBA8 (probably BGRA8 in practice, driver takes care) // NOTE: On embedded systems, we let the driver choose the best internal format - //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // OpenGL - //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // WebGL - - // TODO: Add support for multiple color modes (16bit color modes and grayscale) - // Ref: https://www.khronos.org/opengles/sdk/docs/man3/html/glTexImage2D.xhtml - // On WebGL, internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA - // (sized)internalFormat format type + + // Support for multiple color modes (16bit color modes and grayscale) + // (sized)internalFormat format type // GL_R GL_RED GL_UNSIGNED_BYTE // GL_RGB565 GL_RGB GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5 - // GL_RGB5_A1 GL_RGBA GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_5_5_1 + // GL_RGB5_A1 GL_RGBA GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_5_5_1 // GL_RGBA4 GL_RGBA GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_4_4_4_4 - // GL_RGBA8 GL_RGBA GL_UNSIGNED_BYTE - // GL_RGB8 GL_RGB GL_UNSIGNED_BYTE + // GL_RGBA8 GL_RGBA GL_UNSIGNED_BYTE + // GL_RGB8 GL_RGB GL_UNSIGNED_BYTE - switch (colorMode) + switch (textureFormat) { - case GRAYSCALE: glTexImage2D(GL_TEXTURE_2D, 0, GL_R, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, data); break; - case R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); break; - case R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); break; - case R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data); break; - case R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); break; - case R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); break; - default: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); break; + case UNCOMPRESSED_GRAYSCALE: + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); + + // With swizzleMask we define how a one channel texture will be mapped to RGBA + // Required GL >= 3.3 or EXT_texture_swizzle/ARB_texture_swizzle + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, 1.0f }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + + TraceLog(INFO, "Grayscale texture loaded and swizzled!"); + } break; + case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case COMPRESSED_DXT1_RGB: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; + case COMPRESSED_DXT1_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break; + case COMPRESSED_DXT3_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; + case COMPRESSED_DXT5_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break; + case COMPRESSED_ETC1_RGB: TraceLog(WARNING, "ETC compression not supported"); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case COMPRESSED_ETC2_RGB: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break;//TraceLog(WARNING, "ETC compression not supported"); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_ETC2_EAC_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break;//TraceLog(WARNING, "ETC compression not supported"); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + //case COMPRESSED_ASTC_RGBA_4x4: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + default: TraceLog(WARNING, "Texture format not recognized"); break; } - if (genMipmaps) + if ((mipmapCount == 1) && (genMipmaps)) + { + glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically + TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically for new texture", id); + } +#elif defined(GRAPHICS_API_OPENGL_ES2) + + // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA + switch (textureFormat) + { + case UNCOMPRESSED_GRAYSCALE: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case COMPRESSED_DXT1_RGB: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; + case COMPRESSED_DXT1_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; + case COMPRESSED_DXT3_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; // NOTE: Not supported by WebGL + case COMPRESSED_DXT5_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break; // NOTE: Not supported by WebGL + case COMPRESSED_ETC1_RGB: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_ETC1_RGB8_OES); break; + case COMPRESSED_ETC2_RGB: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_ETC2_EAC_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + //case COMPRESSED_ASTC_RGBA_4x4: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + default: TraceLog(WARNING, "Texture format not recognized"); break; + } + + if ((mipmapCount == 1) && (genMipmaps)) { glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically for new texture", id); @@ -1638,13 +1722,15 @@ Model rlglLoadModel(VertexData mesh) Model model; model.mesh = mesh; + model.transform = MatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_11) + model.mesh.vaoId = 0; // Vertex Array Object + model.mesh.vboId[0] = 0; // Vertex position VBO + model.mesh.vboId[1] = 0; // Texcoords VBO + model.mesh.vboId[2] = 0; // Normals VBO model.texture.id = 0; // No texture required - model.vaoId = 0; // Vertex Array Object - model.vboId[0] = 0; // Vertex position VBO - model.vboId[1] = 0; // Texcoords VBO - model.vboId[2] = 0; // Normals VBO + model.shader.id = 0; // No shader used #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) model.texture.id = whiteTexture; // Default whiteTexture @@ -1681,109 +1767,31 @@ Model rlglLoadModel(VertexData mesh) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW); glEnableVertexAttribArray(simpleShader.normalLoc); glVertexAttribPointer(simpleShader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - + model.shader = simpleShader; // By default, simple shader will be used - model.vboId[0] = vertexBuffer[0]; // Vertex position VBO - model.vboId[1] = vertexBuffer[1]; // Texcoords VBO - model.vboId[2] = vertexBuffer[2]; // Normals VBO + model.mesh.vboId[0] = vertexBuffer[0]; // Vertex position VBO + model.mesh.vboId[1] = vertexBuffer[1]; // Texcoords VBO + model.mesh.vboId[2] = vertexBuffer[2]; // Normals VBO if (vaoSupported) { if (vaoModel > 0) { - model.vaoId = vaoModel; + model.mesh.vaoId = vaoModel; TraceLog(INFO, "[VAO ID %i] Model uploaded successfully to VRAM (GPU)", vaoModel); } else TraceLog(WARNING, "Model could not be uploaded to VRAM (GPU)"); } else { - TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Model uploaded successfully to VRAM (GPU)", model.vboId[0], model.vboId[1], model.vboId[2]); + TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Model uploaded successfully to VRAM (GPU)", model.mesh.vboId[0], model.mesh.vboId[1], model.mesh.vboId[2]); } #endif return model; } -// Convert image data to OpenGL texture (returns OpenGL valid Id) -// NOTE: Expected compressed image data and POT image -unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compFormat) -{ - GLuint id; - -#if defined(GRAPHICS_API_OPENGL_11) - id = 0; - TraceLog(WARNING, "GPU compressed textures not supported on OpenGL 1.1"); - -#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - TraceLog(DEBUG, "Compressed texture width: %i", width); - TraceLog(DEBUG, "Compressed texture height: %i", height); - TraceLog(DEBUG, "Compressed texture mipmap levels: %i", mipmapCount); - TraceLog(DEBUG, "Compressed texture format: 0x%x", compFormat); - - if (compFormat == 0) - { - id = 0; - TraceLog(WARNING, "Texture compressed format not recognized", id); - } - else - { - glGenTextures(1, &id); - - // Bind the texture - glBindTexture(GL_TEXTURE_2D, id); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - // Set texture parameters - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // If mipmaps are being used, we configure mag-min filters accordingly - if (mipmapCount > 1) - { - // Trilinear filtering with mipmaps - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate use of mipmaps (must be available) - } - else - { - // Not using mipmappings - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - } - - int blockSize = 0; - int offset = 0; - - if (compFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) blockSize = 8; - else blockSize = 16; - - // Load the mipmaps - for (int level = 0; level < mipmapCount && (width || height); level++) - { - unsigned int size = 0; - - // NOTE: size specifies the number of bytes of image data (S3TC/DXTC) - if (compFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) size = ((width + 3)/4)*((height + 3)/4)*blockSize; // S3TC/DXTC -#if defined(GRAPHICS_API_OPENGL_ES2) - else if (compFormat == GL_ETC1_RGB8_OES) size = 8*((width + 3) >> 2)*((height + 3) >> 2); // ETC1 -#endif - glCompressedTexImage2D(GL_TEXTURE_2D, level, compFormat, width, height, 0, size, data + offset); - - offset += size; - width /= 2; - height /= 2; - - // Security check for NPOT textures - if (width < 1) width = 1; - if (height < 1) height = 1; - } - } -#endif - - return id; -} #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Load a shader (vertex shader + fragment shader) from text data @@ -1801,7 +1809,7 @@ unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr) glShaderSource(vertexShader, 1, &pvs, NULL); glShaderSource(fragmentShader, 1, &pfs, NULL); - + GLint success = 0; glCompileShader(vertexShader); @@ -1869,9 +1877,9 @@ unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr) glGetProgramInfoLog(program, maxLength, &length, log); TraceLog(INFO, "%s", log); - + glDeleteProgram(program); - + program = 0; } else TraceLog(INFO, "[SHDR ID %i] Shader program loaded successfully", program); @@ -1907,12 +1915,12 @@ unsigned char *rlglReadScreenPixels(int width, int height) return imgData; // NOTE: image data should be freed } -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Load a shader (vertex shader + fragment shader) from text data Shader LoadShader(char *vsFileName, char *fsFileName) { Shader shader; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Shaders loading from external text file char *vShaderStr = TextFileRead(vsFileName); char *fShaderStr = TextFileRead(fsFileName); @@ -1932,7 +1940,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord"); shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal"); // NOTE: custom shader does not use colorLoc - + // Get handles to GLSL uniform locations (vertex shader) shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); @@ -1941,35 +1949,39 @@ Shader LoadShader(char *vsFileName, char *fsFileName) shader.textureLoc = glGetUniformLocation(shader.id, "texture0"); shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor"); //-------------------------------------------------------------------- - +#endif + return shader; } // Link shader to model void SetModelShader(Model *model, Shader shader) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) model->shader = shader; - - if (vaoSupported) glBindVertexArray(model->vaoId); + + if (vaoSupported) glBindVertexArray(model->mesh.vaoId); // Enable vertex attributes: position - glBindBuffer(GL_ARRAY_BUFFER, model->vboId[0]); + glBindBuffer(GL_ARRAY_BUFFER, model->mesh.vboId[0]); glEnableVertexAttribArray(shader.vertexLoc); glVertexAttribPointer(shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); // Enable vertex attributes: texcoords - glBindBuffer(GL_ARRAY_BUFFER, model->vboId[1]); + glBindBuffer(GL_ARRAY_BUFFER, model->mesh.vboId[1]); glEnableVertexAttribArray(shader.texcoordLoc); glVertexAttribPointer(shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); // Enable vertex attributes: normals - glBindBuffer(GL_ARRAY_BUFFER, model->vboId[2]); + glBindBuffer(GL_ARRAY_BUFFER, model->mesh.vboId[2]); glEnableVertexAttribArray(shader.normalLoc); glVertexAttribPointer(shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); if (vaoSupported) glBindVertexArray(0); // Unbind VAO +#endif } +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) void PrintProjectionMatrix() { PrintMatrix(projection); @@ -1979,7 +1991,6 @@ void PrintModelviewMatrix() { PrintMatrix(modelview); } - #endif //---------------------------------------------------------------------------------- @@ -1987,20 +1998,55 @@ void PrintModelviewMatrix() //---------------------------------------------------------------------------------- #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +// Convert image data to OpenGL texture (returns OpenGL valid Id) +// NOTE: Expected compressed image data and POT image +static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat) +{ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + int blockSize = 0; // Bytes every block + int offset = 0; + + if ((compressedFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) || + (compressedFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || +#if defined(GRAPHICS_API_OPENGL_ES2) + (compressedFormat == GL_ETC1_RGB8_OES) || +#endif + (compressedFormat == GL_COMPRESSED_RGB8_ETC2)) blockSize = 8; + else blockSize = 16; + + // Load the mipmap levels + for (int level = 0; level < mipmapCount && (width || height); level++) + { + unsigned int size = 0; + + size = ((width + 3)/4)*((height + 3)/4)*blockSize; + + glCompressedTexImage2D(GL_TEXTURE_2D, level, compressedFormat, width, height, 0, size, data + offset); + + offset += size; + width /= 2; + height /= 2; + + // Security check for NPOT textures + if (width < 1) width = 1; + if (height < 1) height = 1; + } +} // Load Shader (Vertex and Fragment) // NOTE: This shader program is used only for batch buffers (lines, triangles, quads) static Shader LoadDefaultShader(void) { Shader shader; - + // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 // NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+ // Just defined #version 330 despite shader is #version 110 // Vertex shader directly defined, no external file required #if defined(GRAPHICS_API_OPENGL_33) - char vShaderStr[] = " #version 330 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2) + char vShaderStr[] = " #version 110 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2) #elif defined(GRAPHICS_API_OPENGL_ES2) char vShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! #endif @@ -2020,7 +2066,7 @@ static Shader LoadDefaultShader(void) // Fragment shader directly defined, no external file required #if defined(GRAPHICS_API_OPENGL_33) - char fShaderStr[] = " #version 330 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2) + char fShaderStr[] = " #version 110 \n" // NOTE: Actually, #version 110 (quivalent to #version 100 on ES2) #elif defined(GRAPHICS_API_OPENGL_ES2) char fShaderStr[] = " #version 100 \n" // NOTE: Must be defined this way! 110 doesn't work! "precision mediump float; \n" // WebGL, required for emscripten @@ -2037,14 +2083,14 @@ static Shader LoadDefaultShader(void) if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); - + // Get handles to GLSL input attibute locations //------------------------------------------------------------------- shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition"); shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord"); shader.colorLoc = glGetAttribLocation(shader.id, "vertexColor"); // NOTE: default shader does not use normalLoc - + // Get handles to GLSL uniform locations (vertex shader) shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); @@ -2061,7 +2107,7 @@ static Shader LoadDefaultShader(void) static Shader LoadSimpleShader(void) { Shader shader; - + // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 // NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+ // Just defined #version 330 despite shader is #version 110 @@ -2103,14 +2149,14 @@ static Shader LoadSimpleShader(void) if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Simple shader loaded successfully", shader.id); else TraceLog(WARNING, "[SHDR ID %i] Simple shader could not be loaded", shader.id); - + // Get handles to GLSL input attibute locations //------------------------------------------------------------------- shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition"); shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord"); shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal"); // NOTE: simple shader does not use colorLoc - + // Get handles to GLSL uniform locations (vertex shader) shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); diff --git a/src/rlgl.h b/src/rlgl.h index e277b2507..c1d71cc91 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -88,35 +88,47 @@ typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode; typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; -typedef enum { GRAYSCALE = 0, R5G6B5, R8G8B8, R5G5B5A1, R4G4B4A4, R8G8B8A8 } ColorMode; - #ifdef RLGL_STANDALONE + // Texture formats (support depends on OpenGL version) + typedef enum { + UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) + UNCOMPRESSED_R5G6B5, // 16 bpp + UNCOMPRESSED_R8G8B8, // 24 bpp + UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha) + UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha) + UNCOMPRESSED_R8G8B8A8, // 32 bpp + COMPRESSED_DXT1_RGB, // 4 bpp (no alpha) + COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha) + COMPRESSED_DXT3_RGBA, // 8 bpp + COMPRESSED_DXT5_RGBA, // 8 bpp + COMPRESSED_ETC1_RGB, // 4 bpp + COMPRESSED_ETC2_RGB, // 4 bpp + COMPRESSED_ETC2_EAC_RGBA, // 8 bpp + /*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp + } TextureFormat; + // VertexData type + // NOTE: If using OpenGL 1.1, data loaded in CPU; if OpenGL 3.3+ data loaded in GPU (vaoId) typedef struct VertexData { int vertexCount; float *vertices; // 3 components per vertex float *texcoords; // 2 components per vertex float *normals; // 3 components per vertex unsigned char *colors; + unsigned int vaoId; + unsigned int vboId[4]; } VertexData; - - // Texture2D type - typedef struct Texture2D { - unsigned int id; // Texture id - int width; - int height; - } Texture2D; // Shader type typedef struct Shader { unsigned int id; // Shader program id - + // Variable attributes unsigned int vertexLoc; // Vertex attribute location point (vertex shader) unsigned int texcoordLoc; // Texcoord attribute location point (vertex shader) unsigned int normalLoc; // Normal attribute location point (vertex shader) unsigned int colorLoc; // Color attibute location point (vertex shader) - + // Uniforms unsigned int projectionLoc; // Projection matrix uniform location point (vertex shader) unsigned int modelviewLoc; // ModeView matrix uniform location point (vertex shader) @@ -125,15 +137,19 @@ typedef enum { GRAYSCALE = 0, R5G6B5, R8G8B8, R5G5B5A1, R4G4B4A4, R8G8B8A8 } Col } Shader; // 3d Model type - // NOTE: If using OpenGL 1.1, loaded in CPU (mesh); if OpenGL 3.3+ loaded in GPU (vaoId) typedef struct Model { VertexData mesh; - unsigned int vaoId; - unsigned int vboId[4]; + Matrix transform; Texture2D texture; Shader shader; - //Matrix transform; } Model; + + // Texture2D type + typedef struct Texture2D { + unsigned int id; // Texture id + int width; + int height; + } Texture2D; #endif #ifdef __cplusplus @@ -181,28 +197,27 @@ void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) int rlGetVersion(void); // Returns current OpenGL version -void rlEnableFBO(void); +void rlEnableFBO(void); // Enable rendering to postprocessing FBO //------------------------------------------------------------------------------------ // Functions Declaration - rlgl functionality //------------------------------------------------------------------------------------ void rlglInit(void); // Initialize rlgl (shaders, VAO, VBO...) -void rlglInitPostpro(void); // Initialize postprocessing system void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO -void rlglDrawPostpro(unsigned int shaderId); // Draw with postpro shader void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff) -Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates -unsigned int rlglLoadTexture(unsigned char *data, int width, int height, int colorMode, bool genMipmaps); // Load in GPU OpenGL texture -unsigned int rlglLoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int format); -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr); // Load a shader from text data -#endif +unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps); // Load in GPU OpenGL texture +unsigned int rlglLoadShader(char *vShaderStr, char *fShaderStr); // Load a shader from text data +void rlglInitPostpro(void); // Initialize postprocessing system +void rlglDrawPostpro(void); // Draw with postprocessing shader +void rlglSetPostproShader(Shader shader); // Set postprocessing shader Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires); +Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates + byte *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) diff --git a/src/shapes.c b/src/shapes.c index d872eacfe..d88845cc7 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -98,7 +98,7 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color) // Draw a color-filled circle void DrawCircle(int centerX, int centerY, float radius, Color color) { - DrawPoly((Vector2){centerX, centerY}, 360, radius, 0, color); + DrawPoly((Vector2){ centerX, centerY }, 36, radius, 0, color); } // Draw a gradient-filled circle @@ -106,14 +106,14 @@ void DrawCircle(int centerX, int centerY, float radius, Color color) void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2) { rlBegin(RL_TRIANGLES); - for (int i=0; i < 360; i += 2) + for (int i = 0; i < 360; i += 10) { rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(centerX, centerY); rlColor4ub(color2.r, color2.g, color2.b, color2.a); - rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius); + rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); rlColor4ub(color2.r, color2.g, color2.b, color2.a); - rlVertex2f(centerX + sin(DEG2RAD*(i+2)) * radius, centerY + cos(DEG2RAD*(i+2)) * radius); + rlVertex2f(centerX + sin(DEG2RAD*(i + 10)) * radius, centerY + cos(DEG2RAD*(i + 10))*radius); } rlEnd(); } @@ -122,12 +122,12 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co void DrawCircleV(Vector2 center, float radius, Color color) { rlBegin(RL_TRIANGLES); - for (int i=0; i < 360; i += 2) + for (int i = 0; i < 360; i += 10) { rlColor4ub(color.r, color.g, color.b, color.a); rlVertex2i(center.x, center.y); - rlVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius); - rlVertex2f(center.x + sin(DEG2RAD*(i+2)) * radius, center.y + cos(DEG2RAD*(i+2)) * radius); + rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius); + rlVertex2f(center.x + sin(DEG2RAD*(i + 10)) * radius, center.y + cos(DEG2RAD*(i + 10)) * radius); } rlEnd(); } @@ -139,10 +139,10 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color) rlColor4ub(color.r, color.g, color.b, color.a); // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360) - for (int i=0; i < 360; i++) + for (int i = 0; i < 360; i += 10) { - rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius); - rlVertex2f(centerX + sin(DEG2RAD*(i+1)) * radius, centerY + cos(DEG2RAD*(i+1)) * radius); + rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); + rlVertex2f(centerX + sin(DEG2RAD*(i + 10)) * radius, centerY + cos(DEG2RAD*(i + 10))*radius); } rlEnd(); } @@ -201,7 +201,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color) rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); - rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer + rlNormal3f(0.0f, 0.0f, 1.0f); rlTexCoord2f(0.0f, 0.0f); rlVertex2f(position.x, position.y); @@ -275,13 +275,13 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col rlRotatef(rotation, 0, 0, 1); rlBegin(RL_TRIANGLES); - for (int i=0; i < 360; i += 360/sides) + for (int i = 0; i < 360; i += 360/sides) { rlColor4ub(color.r, color.g, color.b, color.a); rlVertex2i(0, 0); - rlVertex2f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius); - rlVertex2f(sin(DEG2RAD*(i+360/sides)) * radius, cos(DEG2RAD*(i+360/sides)) * radius); + rlVertex2f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius); + rlVertex2f(sin(DEG2RAD*(i + 360/sides))*radius, cos(DEG2RAD*(i + 360/sides))*radius); } rlEnd(); rlPopMatrix(); @@ -299,8 +299,8 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color) for (int i = 0; i < numPoints - 2; i++) { rlVertex2f(points[i].x, points[i].y); - rlVertex2f(points[i+1].x, points[i+1].y); - rlVertex2f(points[i+2].x, points[i+2].y); + rlVertex2f(points[i + 1].x, points[i + 1].y); + rlVertex2f(points[i + 2].x, points[i + 2].y); } rlEnd(); } @@ -318,7 +318,7 @@ void DrawPolyExLines(Vector2 *points, int numPoints, Color color) for (int i = 0; i < numPoints - 1; i++) { rlVertex2f(points[i].x, points[i].y); - rlVertex2f(points[i+1].x, points[i+1].y); + rlVertex2f(points[i + 1].x, points[i + 1].y); } rlEnd(); } @@ -367,10 +367,10 @@ bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2) { bool collision = false; - int dx = abs((rec1.x + rec1.width / 2) - (rec2.x + rec2.width / 2)); - int dy = abs((rec1.y + rec1.height / 2) - (rec2.y + rec2.height / 2)); + int dx = abs((rec1.x + rec1.width/2) - (rec2.x + rec2.width/2)); + int dy = abs((rec1.y + rec1.height/2) - (rec2.y + rec2.height/2)); - if ((dx <= (rec1.width / 2 + rec2.width / 2)) && ((dy <= (rec1.height / 2 + rec2.height / 2)))) collision = true; + if ((dx <= (rec1.width/2 + rec2.width/2)) && ((dy <= (rec1.height/2 + rec2.height/2)))) collision = true; return collision; } @@ -395,10 +395,10 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) { bool collision = false; - float dx = abs((rec.x + rec.width / 2) - center.x); - float dy = abs((rec.y + rec.height / 2) - center.y); + float dx = abs((rec.x + rec.width/2) - center.x); + float dy = abs((rec.y + rec.height/2) - center.y); - if ((dx <= (rec.width / 2 + radius)) && (dy <= (rec.height / 2 + radius))) collision = true; + if ((dx <= (rec.width/2 + radius)) && (dy <= (rec.height/2 + radius))) collision = true; return collision; } diff --git a/src/text.c b/src/text.c index 86d58b1ab..7b3fc7d2f 100644 --- a/src/text.c +++ b/src/text.c @@ -30,10 +30,9 @@ #include // Used for functions with variable number of parameters (FormatText()) #include // Standard input / output lib -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 -#include "utils.h" // Required for function GetExtendion() +#include "utils.h" // Required for function GetExtension() -// Following libs will be used on LoadTTF() +// Following libs are used on LoadTTF() #define STB_TRUETYPE_IMPLEMENTATION #define STB_RECT_PACK_IMPLEMENTATION #include "stb_rect_pack.h" @@ -44,7 +43,7 @@ //---------------------------------------------------------------------------------- #define FONT_FIRST_CHAR 32 #define MAX_FONTCHARS 128 -#define MAX_FORMATTEXT_LENGTH 50 +#define MAX_FORMATTEXT_LENGTH 64 #define BIT_CHECK(a,b) ((a) & (1<<(b))) @@ -82,7 +81,7 @@ extern void LoadDefaultFont(void) { // NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement // http://www.utf8-chartable.de/unicode-utf8-table.pl - + defaultFont.numChars = 224; // Number of chars included in our default font Image image; @@ -93,60 +92,60 @@ extern void LoadDefaultFont(void) // This way, we reconstruct SpriteFont without creating large global variables // This data is automatically allocated to Stack and automatically deallocated at the end of this function int defaultFontData[512] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200020, 0x0001b000, 0x00000000, 0x00000000, 0x8ef92520, 0x00020a00, 0x7dbe8000, 0x1f7df45f, - 0x4a2bf2a0, 0x0852091e, 0x41224000, 0x10041450, 0x2e292020, 0x08220812, 0x41222000, 0x10041450, 0x10f92020, 0x3efa084c, 0x7d22103c, 0x107df7de, - 0xe8a12020, 0x08220832, 0x05220800, 0x10450410, 0xa4a3f000, 0x08520832, 0x05220400, 0x10450410, 0xe2f92020, 0x0002085e, 0x7d3e0281, 0x107df41f, - 0x00200000, 0x8001b000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0000fbe, 0xfbf7e00f, 0x5fbf7e7d, 0x0050bee8, 0x440808a2, 0x0a142fe8, 0x50810285, 0x0050a048, - 0x49e428a2, 0x0a142828, 0x40810284, 0x0048a048, 0x10020fbe, 0x09f7ebaf, 0xd89f3e84, 0x0047a04f, 0x09e48822, 0x0a142aa1, 0x50810284, 0x0048a048, - 0x04082822, 0x0a142fa0, 0x50810285, 0x0050a248, 0x00008fbe, 0xfbf42021, 0x5f817e7d, 0x07d09ce8, 0x00008000, 0x00000fe0, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000c0180, - 0xdfbf4282, 0x0bfbf7ef, 0x42850505, 0x004804bf, 0x50a142c6, 0x08401428, 0x42852505, 0x00a808a0, 0x50a146aa, 0x08401428, 0x42852505, 0x00081090, - 0x5fa14a92, 0x0843f7e8, 0x7e792505, 0x00082088, 0x40a15282, 0x08420128, 0x40852489, 0x00084084, 0x40a16282, 0x0842022a, 0x40852451, 0x00088082, - 0xc0bf4282, 0xf843f42f, 0x7e85fc21, 0x3e0900bf, 0x00000000, 0x00000004, 0x00000000, 0x000c0180, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000402, 0x41482000, 0x00000000, 0x00000800, - 0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820, - 0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0, - 0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x06000000, 0x24000000, 0x00000901, 0x00000000, 0x09108000, - 0x24fa28a2, 0x00000901, 0x00000000, 0x013e0000, 0x2242252a, 0x00000952, 0x00000000, 0x038a8000, 0x2422222a, 0x00000929, 0x00000000, 0x010a8000, - 0x2412252a, 0x00000901, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000901, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000, - 0x0003e000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03, - 0x02bea080, 0xf0000020, 0xc452208a, 0x04202b02, 0xf8029122, 0x07f0003b, 0xe44b388e, 0x02203a02, 0x081e8a1c, 0x0411e92a, 0xf4420be0, 0x01248202, - 0xe8140414, 0x05d104ba, 0xe7c3b880, 0x00893a0a, 0x283c0e1c, 0x04500902, 0xc4400080, 0x00448002, 0xe8208422, 0x04500002, 0x80400000, 0x05200002, - 0x083e8e00, 0x04100002, 0x804003e0, 0x07000042, 0xf8008400, 0x07f00003, 0x80400000, 0x04000022, 0x00000000, 0x00000000, 0x80400000, 0x04000002, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800702, 0x1848a0c2, 0x84010000, 0x02920921, 0x01042642, 0x00005121, 0x42023f7f, 0x00291002, - 0xefc01422, 0x7efdfbf7, 0xefdfa109, 0x03bbbbf7, 0x28440f12, 0x42850a14, 0x20408109, 0x01111010, 0x28440408, 0x42850a14, 0x2040817f, 0x01111010, - 0xefc78204, 0x7efdfbf7, 0xe7cf8109, 0x011111f3, 0x2850a932, 0x42850a14, 0x2040a109, 0x01111010, 0x2850b840, 0x42850a14, 0xefdfbf79, 0x03bbbbf7, - 0x001fa020, 0x00000000, 0x00001000, 0x00000000, 0x00002070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x08022800, 0x00012283, 0x02430802, 0x01010001, 0x8404147c, 0x20000144, 0x80048404, 0x00823f08, 0xdfbf4284, 0x7e03f7ef, 0x142850a1, 0x0000210a, - 0x50a14684, 0x528a1428, 0x142850a1, 0x03efa17a, 0x50a14a9e, 0x52521428, 0x142850a1, 0x02081f4a, 0x50a15284, 0x4a221428, 0xf42850a1, 0x03efa14b, - 0x50a16284, 0x4a521428, 0x042850a1, 0x0228a17a, 0xdfbf427c, 0x7e8bf7ef, 0xf7efdfbf, 0x03efbd0b, 0x00000000, 0x04000000, 0x00000000, 0x00000008, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200508, 0x00840400, 0x11458122, 0x00014210, - 0x00514294, 0x51420800, 0x20a22a94, 0x0050a508, 0x00200000, 0x00000000, 0x00050000, 0x08000000, 0xfefbefbe, 0xfbefbefb, 0xfbeb9114, 0x00fbefbe, - 0x20820820, 0x8a28a20a, 0x8a289114, 0x3e8a28a2, 0xfefbefbe, 0xfbefbe0b, 0x8a289114, 0x008a28a2, 0x228a28a2, 0x08208208, 0x8a289114, 0x088a28a2, - 0xfefbefbe, 0xfbefbefb, 0xfa2f9114, 0x00fbefbe, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00210100, 0x00000004, 0x00000000, 0x00000000, 0x14508200, 0x00001402, 0x00000000, 0x00000000, - 0x00000010, 0x00000020, 0x00000000, 0x00000000, 0xa28a28be, 0x00002228, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000, - 0xa28a28aa, 0x000022a8, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000, 0xbefbefbe, 0x00003e2f, 0x00000000, 0x00000000, - 0x00000004, 0x00002028, 0x00000000, 0x00000000, 0x80000000, 0x00003e0f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200020, 0x0001b000, 0x00000000, 0x00000000, 0x8ef92520, 0x00020a00, 0x7dbe8000, 0x1f7df45f, + 0x4a2bf2a0, 0x0852091e, 0x41224000, 0x10041450, 0x2e292020, 0x08220812, 0x41222000, 0x10041450, 0x10f92020, 0x3efa084c, 0x7d22103c, 0x107df7de, + 0xe8a12020, 0x08220832, 0x05220800, 0x10450410, 0xa4a3f000, 0x08520832, 0x05220400, 0x10450410, 0xe2f92020, 0x0002085e, 0x7d3e0281, 0x107df41f, + 0x00200000, 0x8001b000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0000fbe, 0xfbf7e00f, 0x5fbf7e7d, 0x0050bee8, 0x440808a2, 0x0a142fe8, 0x50810285, 0x0050a048, + 0x49e428a2, 0x0a142828, 0x40810284, 0x0048a048, 0x10020fbe, 0x09f7ebaf, 0xd89f3e84, 0x0047a04f, 0x09e48822, 0x0a142aa1, 0x50810284, 0x0048a048, + 0x04082822, 0x0a142fa0, 0x50810285, 0x0050a248, 0x00008fbe, 0xfbf42021, 0x5f817e7d, 0x07d09ce8, 0x00008000, 0x00000fe0, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000c0180, + 0xdfbf4282, 0x0bfbf7ef, 0x42850505, 0x004804bf, 0x50a142c6, 0x08401428, 0x42852505, 0x00a808a0, 0x50a146aa, 0x08401428, 0x42852505, 0x00081090, + 0x5fa14a92, 0x0843f7e8, 0x7e792505, 0x00082088, 0x40a15282, 0x08420128, 0x40852489, 0x00084084, 0x40a16282, 0x0842022a, 0x40852451, 0x00088082, + 0xc0bf4282, 0xf843f42f, 0x7e85fc21, 0x3e0900bf, 0x00000000, 0x00000004, 0x00000000, 0x000c0180, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000402, 0x41482000, 0x00000000, 0x00000800, + 0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820, + 0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0, + 0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x06000000, 0x24000000, 0x00000901, 0x00000000, 0x09108000, + 0x24fa28a2, 0x00000901, 0x00000000, 0x013e0000, 0x2242252a, 0x00000952, 0x00000000, 0x038a8000, 0x2422222a, 0x00000929, 0x00000000, 0x010a8000, + 0x2412252a, 0x00000901, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000901, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000, + 0x0003e000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03, + 0x02bea080, 0xf0000020, 0xc452208a, 0x04202b02, 0xf8029122, 0x07f0003b, 0xe44b388e, 0x02203a02, 0x081e8a1c, 0x0411e92a, 0xf4420be0, 0x01248202, + 0xe8140414, 0x05d104ba, 0xe7c3b880, 0x00893a0a, 0x283c0e1c, 0x04500902, 0xc4400080, 0x00448002, 0xe8208422, 0x04500002, 0x80400000, 0x05200002, + 0x083e8e00, 0x04100002, 0x804003e0, 0x07000042, 0xf8008400, 0x07f00003, 0x80400000, 0x04000022, 0x00000000, 0x00000000, 0x80400000, 0x04000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800702, 0x1848a0c2, 0x84010000, 0x02920921, 0x01042642, 0x00005121, 0x42023f7f, 0x00291002, + 0xefc01422, 0x7efdfbf7, 0xefdfa109, 0x03bbbbf7, 0x28440f12, 0x42850a14, 0x20408109, 0x01111010, 0x28440408, 0x42850a14, 0x2040817f, 0x01111010, + 0xefc78204, 0x7efdfbf7, 0xe7cf8109, 0x011111f3, 0x2850a932, 0x42850a14, 0x2040a109, 0x01111010, 0x2850b840, 0x42850a14, 0xefdfbf79, 0x03bbbbf7, + 0x001fa020, 0x00000000, 0x00001000, 0x00000000, 0x00002070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x08022800, 0x00012283, 0x02430802, 0x01010001, 0x8404147c, 0x20000144, 0x80048404, 0x00823f08, 0xdfbf4284, 0x7e03f7ef, 0x142850a1, 0x0000210a, + 0x50a14684, 0x528a1428, 0x142850a1, 0x03efa17a, 0x50a14a9e, 0x52521428, 0x142850a1, 0x02081f4a, 0x50a15284, 0x4a221428, 0xf42850a1, 0x03efa14b, + 0x50a16284, 0x4a521428, 0x042850a1, 0x0228a17a, 0xdfbf427c, 0x7e8bf7ef, 0xf7efdfbf, 0x03efbd0b, 0x00000000, 0x04000000, 0x00000000, 0x00000008, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200508, 0x00840400, 0x11458122, 0x00014210, + 0x00514294, 0x51420800, 0x20a22a94, 0x0050a508, 0x00200000, 0x00000000, 0x00050000, 0x08000000, 0xfefbefbe, 0xfbefbefb, 0xfbeb9114, 0x00fbefbe, + 0x20820820, 0x8a28a20a, 0x8a289114, 0x3e8a28a2, 0xfefbefbe, 0xfbefbe0b, 0x8a289114, 0x008a28a2, 0x228a28a2, 0x08208208, 0x8a289114, 0x088a28a2, + 0xfefbefbe, 0xfbefbefb, 0xfa2f9114, 0x00fbefbe, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00210100, 0x00000004, 0x00000000, 0x00000000, 0x14508200, 0x00001402, 0x00000000, 0x00000000, + 0x00000010, 0x00000020, 0x00000000, 0x00000000, 0xa28a28be, 0x00002228, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000, + 0xa28a28aa, 0x000022a8, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000, 0xbefbefbe, 0x00003e2f, 0x00000000, 0x00000000, + 0x00000004, 0x00002028, 0x00000000, 0x00000000, 0x80000000, 0x00003e0f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; int charsHeight = 10; int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically int charsWidth[224] = { 3, 1, 4, 6, 5, 7, 6, 2, 3, 3, 5, 5, 2, 4, 1, 7, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 3, 4, 3, 6, - 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5, - 2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 5, 5, 5, 7, 1, 5, 3, 7, 3, 5, 4, 1, 7, 4, 3, 5, 3, 3, 2, 5, 6, 1, 2, 2, 3, 5, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 3, 3, 3, 3, 7, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 4, 6, - 5, 5, 5, 5, 5, 5, 9, 5, 5, 5, 5, 5, 2, 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5 }; + 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5, + 2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 5, 5, 5, 7, 1, 5, 3, 7, 3, 5, 4, 1, 7, 4, 3, 5, 3, 3, 2, 5, 6, 1, 2, 2, 3, 5, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 3, 3, 3, 3, 7, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 4, 6, + 5, 5, 5, 5, 5, 5, 9, 5, 5, 5, 5, 5, 2, 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5 }; // Re-construct image from defaultFontData and generate OpenGL texture //---------------------------------------------------------------------- @@ -168,7 +167,7 @@ extern void LoadDefaultFont(void) if (counter > 512) counter = 0; // Security check... } - + //FILE *myimage = fopen("default_font.raw", "wb"); //fwrite(image.pixels, 1, 128*128*4, myimage); //fclose(myimage); @@ -211,7 +210,7 @@ extern void LoadDefaultFont(void) extern void UnloadDefaultFont(void) { - rlDeleteTextures(defaultFont.texture.id); + UnloadTexture(defaultFont.texture); free(defaultFont.charSet); } @@ -258,7 +257,7 @@ SpriteFont LoadSpriteFont(const char *fileName) // Unload SpriteFont from GPU memory void UnloadSpriteFont(SpriteFont spriteFont) { - rlDeleteTextures(spriteFont.texture.id); + UnloadTexture(spriteFont.texture); free(spriteFont.charSet); } @@ -284,54 +283,35 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color) void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int fontSize, int spacing, Color tint) { int length = strlen(text); - int positionX = (int)position.x; + int offsetX = 0; float scaleFactor; unsigned char letter; - + Character c; if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f; else scaleFactor = (float)fontSize / spriteFont.charSet[0].h; - rlEnableTexture(spriteFont.texture.id); - - rlBegin(RL_QUADS); - for(int i = 0; i < length; i++) + for(int i = 0; i < length; i++) + { + if ((unsigned char)text[i] == 0xc2) { - if ((unsigned char)text[i] == 0xc2) - { - letter = (unsigned char)text[i + 1]; - c = spriteFont.charSet[letter - FONT_FIRST_CHAR]; - i++; - } - else if ((unsigned char)text[i] == 0xc3) - { - letter = (unsigned char)text[i + 1]; - c = spriteFont.charSet[letter - FONT_FIRST_CHAR + 64]; - i++; - } - else c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR]; - - rlColor4ub(tint.r, tint.g, tint.b, tint.a); - rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer - - rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); - rlVertex2f(positionX, position.y); - - rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); - rlVertex2f(positionX, position.y + c.h*scaleFactor); - - rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); - rlVertex2f(positionX + c.w*scaleFactor, position.y + (c.h) * scaleFactor); - - rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); - rlVertex2f(positionX + c.w*scaleFactor, position.y); - - positionX += (c.w*scaleFactor + spacing); + letter = (unsigned char)text[i + 1]; + c = spriteFont.charSet[letter - FONT_FIRST_CHAR]; + i++; } - rlEnd(); + else if ((unsigned char)text[i] == 0xc3) + { + letter = (unsigned char)text[i + 1]; + c = spriteFont.charSet[letter - FONT_FIRST_CHAR + 64]; + i++; + } + else c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR]; - rlDisableTexture(); + DrawTexturePro(spriteFont.texture, (Rectangle){ c.x, c.y, c.w, c.h }, (Rectangle){ position.x + offsetX, position.y, c.w*scaleFactor, c.h*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint); + + offsetX += (c.w*scaleFactor + spacing); + } } // Formatting of text with variables to 'embed' diff --git a/src/textures.c b/src/textures.c index c56816e0a..e45739ac3 100644 --- a/src/textures.c +++ b/src/textures.c @@ -51,10 +51,8 @@ typedef struct { unsigned char *data; // Image raw data int width; // Image base width int height; // Image base height - //int bpp; // bytes per pixel - //int components; // num color components int mipmaps; // Mipmap levels, 1 by default - int compFormat; // Compressed data format, 0 if no compression + int format; // Data format } ImageEx; //---------------------------------------------------------------------------------- @@ -134,7 +132,7 @@ Image LoadImage(const char *fileName) ImageEx imageDDS = LoadDDS(fileName); - if (imageDDS.compFormat == 0) + if (imageDDS.format == 0) { image.pixels = (Color *)malloc(imageDDS.width * imageDDS.height * sizeof(Color)); image.width = imageDDS.width; @@ -304,14 +302,7 @@ Texture2D LoadTexture(const char *fileName) { ImageEx image = LoadDDS(fileName); - if (image.compFormat == 0) - { - texture.id = rlglLoadTexture(image.data, image.width, image.height, R8G8B8A8, false); - } - else - { - texture.id = rlglLoadCompressedTexture(image.data, image.width, image.height, image.mipmaps, image.compFormat); - } + texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps, false); texture.width = image.width; texture.height = image.height; @@ -325,7 +316,7 @@ Texture2D LoadTexture(const char *fileName) { ImageEx image = LoadPKM(fileName); - texture.id = rlglLoadCompressedTexture(image.data, image.width, image.height, image.mipmaps, image.compFormat); + texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps, false); texture.width = image.width; texture.height = image.height; @@ -352,7 +343,17 @@ Texture2D LoadTexture(const char *fileName) return texture; } -// TODO: Texture2D LoadTextureEx(const char *imageData, int width, int height, int colorMode) +Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps) +{ + Texture2D texture; + + texture.width = width; + texture.height = height; + + texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount, genMipmaps); + + return texture; +} // Load a texture from image data // NOTE: image is not unloaded, it must be done manually @@ -382,7 +383,7 @@ Texture2D LoadTextureFromImage(Image image, bool genMipmaps) } // NOTE: rlglLoadTexture() can generate mipmaps (POT image required) - texture.id = rlglLoadTexture(imgData, image.width, image.height, R8G8B8A8, genMipmaps); + texture.id = rlglLoadTexture(imgData, image.width, image.height, UNCOMPRESSED_R8G8B8A8, 1, genMipmaps); texture.width = image.width; texture.height = image.height; @@ -494,7 +495,7 @@ void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Co Rectangle destRec = { (int)position.x, (int)position.y, sourceRec.width, sourceRec.height }; Vector2 origin = { 0, 0 }; - DrawTexturePro(texture, sourceRec, destRec, origin, 0, tint); + DrawTexturePro(texture, sourceRec, destRec, origin, 0.0f, tint); } // Draw a part of a texture (defined by a rectangle) with 'pro' parameters @@ -545,18 +546,6 @@ static ImageEx LoadDDS(const char *fileName) #define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII #define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII - #ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT - #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 - #endif - - #ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT - #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 - #endif - - #ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT - #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - #endif - // DDS Pixel Format typedef struct { unsigned int size; @@ -594,7 +583,7 @@ static ImageEx LoadDDS(const char *fileName) image.width = 0; image.height = 0; image.mipmaps = 0; - image.compFormat = 0; + image.format = 0; FILE *ddsFile = fopen(fileName, "rb"); @@ -626,8 +615,6 @@ static ImageEx LoadDDS(const char *fileName) image.width = header.width; image.height = header.height; - image.mipmaps = 1; - image.compFormat = 0; if (header.ddspf.flags == 0x40 && header.ddspf.rgbBitCount == 24) // DDS_RGB, no compressed { @@ -649,8 +636,11 @@ static ImageEx LoadDDS(const char *fileName) *dest++ = 255; } } - + free(buffer); + + image.mipmaps = 1; + image.format = UNCOMPRESSED_R8G8B8; } else if (header.ddspf.flags == 0x41 && header.ddspf.rgbBitCount == 32) // DDS_RGBA, no compressed { @@ -659,18 +649,20 @@ static ImageEx LoadDDS(const char *fileName) fread(image.data, image.width*image.height*4, 1, ddsFile); image.mipmaps = 1; - image.compFormat = 0; + image.format = UNCOMPRESSED_R8G8B8A8; } - else if ((header.ddspf.flags == 0x04) && (header.ddspf.fourCC > 0)) + else if (((header.ddspf.flags == 0x04) || (header.ddspf.flags == 0x05)) && (header.ddspf.fourCC > 0)) { - TraceLog(WARNING, "[%s] DDS image uses compression, not supported on OpenGL 1.1", fileName); - TraceLog(WARNING, "[%s] DDS compressed files require OpenGL 3.2+ or ES 2.0", fileName); + //TraceLog(WARNING, "[%s] DDS image uses compression, not supported on OpenGL 1.1", fileName); + //TraceLog(WARNING, "[%s] DDS compressed files require OpenGL 3.2+ or ES 2.0", fileName); int bufsize; // Calculate data size, including all mipmaps if (header.mipMapCount > 1) bufsize = header.pitchOrLinearSize * 2; else bufsize = header.pitchOrLinearSize; + + TraceLog(DEBUG, "Pitch or linear size: %i", header.pitchOrLinearSize); image.data = (unsigned char*)malloc(bufsize * sizeof(unsigned char)); @@ -680,19 +672,18 @@ static ImageEx LoadDDS(const char *fileName) fclose(ddsFile); image.mipmaps = header.mipMapCount; - image.compFormat = 0; switch(header.ddspf.fourCC) { - case FOURCC_DXT1: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break; - case FOURCC_DXT3: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; - case FOURCC_DXT5: image.compFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; + case FOURCC_DXT1: + { + if (header.ddspf.flags == 0x04) image.format = COMPRESSED_DXT1_RGB; + else image.format = COMPRESSED_DXT1_RGBA; + } break; + case FOURCC_DXT3: image.format = COMPRESSED_DXT3_RGBA; break; + case FOURCC_DXT5: image.format = COMPRESSED_DXT5_RGBA; break; default: break; } - - // NOTE: Image num color components not required... for now... - //if (fourCC == FOURCC_DXT1) image.components = 3; - //else image.components = 4; } } } @@ -708,10 +699,6 @@ static ImageEx LoadPKM(const char *fileName) // If OpenGL ES 2.0. the following format could be supported (ETC1): //GL_ETC1_RGB8_OES - #ifndef GL_ETC1_RGB8_OES - #define GL_ETC1_RGB8_OES 0x8D64 - #endif - // If OpenGL ES 3.0, the following formats are supported (ETC2/EAC): //GL_COMPRESSED_RGB8_ETC2 //GL_COMPRESSED_RGBA8_ETC2 @@ -780,7 +767,7 @@ static ImageEx LoadPKM(const char *fileName) image.width = width; image.height = height; image.mipmaps = 1; - image.compFormat = GL_ETC1_RGB8_OES; + image.format = COMPRESSED_ETC1_RGB; } }