Compare commits
477 Commits
6.0
...
a043255aa7
| Author | SHA1 | Date | |
|---|---|---|---|
| a043255aa7 | |||
| 8c23ce44a0 | |||
| 48aaf6e2df | |||
| 0ed3570469 | |||
| 2dee47282a | |||
| 607a659363 | |||
| 040a4bafa9 | |||
| 8571d445e9 | |||
| 4722c9fa58 | |||
| 91d50e2938 | |||
| 92f1f3d5d5 | |||
| f0736f6fb5 | |||
| e18de07224 | |||
| 3c1ab87ae1 | |||
| e8b23bfbe4 | |||
| e5c0709fa2 | |||
| 30fa673ef2 | |||
| 5c9e83e642 | |||
| 791dd6d627 | |||
| a9e3027ebc | |||
| 0e8385c890 | |||
| 98ff2c33fe | |||
| a2ee68ea46 | |||
| d8ddc8a0a6 | |||
| 8341321d1a | |||
| 51d713d54d | |||
| 3ff30034de | |||
| 012e274ae8 | |||
| 987a0e54c7 | |||
| ab23bd388e | |||
| 38dad693fe | |||
| d2d6fe6ef9 | |||
| 47dea9b452 | |||
| 002f0310f3 | |||
| 2ca7349a0c | |||
| 3b028f0a17 | |||
| 83b9c17366 | |||
| 5496945d8b | |||
| 6ecf21f700 | |||
| ff7afc6ae1 | |||
| 9b4fa3a40e | |||
| 2fbb15f49a | |||
| d6d163c061 | |||
| f2d8a033bf | |||
| ae55beabe5 | |||
| fafa2cea97 | |||
| 0152c69b95 | |||
| 5c41230605 | |||
| 79046d32b7 | |||
| e33f1cbd15 | |||
| 84cab61804 | |||
| 46395747e3 | |||
| 65d28cf605 | |||
| cb95b8fba7 | |||
| fc03d77be9 | |||
| 8b165ae482 | |||
| fec0780484 | |||
| 1b1925e1d2 | |||
| 938a22e460 | |||
| 5f886e208a | |||
| d33888dd28 | |||
| 5f83146cac | |||
| c042cdc025 | |||
| 7bb0345f32 | |||
| 0b63a64e6f | |||
| 49fe008c36 | |||
| 425e58ced9 | |||
| 77967288d1 | |||
| d0cec73467 | |||
| b927f1b2b1 | |||
| a365e5617a | |||
| 250f2cf243 | |||
| 16a8fb93f4 | |||
| c6e5cbcdd5 | |||
| 2525c16f4b | |||
| dba9f418c1 | |||
| 260d270c58 | |||
| bdf10f516c | |||
| 6f5f7acdd6 | |||
| 3d8a9729f9 | |||
| e981377f65 | |||
| 88b17d974f | |||
| 6715a6ea95 | |||
| 010647936f | |||
| d5d7b948e1 | |||
| f3bcaf978f | |||
| 87ce282eee | |||
| c172619cda | |||
| 8564d55149 | |||
| a414da391b | |||
| 9f59089de1 | |||
| 2f699f6bf0 | |||
| 98c175e692 | |||
| 2f768eb670 | |||
| 98f170c1d2 | |||
| 75909072c2 | |||
| 647755ad6d | |||
| 77450a6abb | |||
| 01d9ad64fb | |||
| abd4cd1155 | |||
| 569ce9b2ec | |||
| 3a7aa76509 | |||
| 73dce3635c | |||
| c66c92962b | |||
| 94a69ad9e2 | |||
| f25c8241f3 | |||
| 2b991b0243 | |||
| c64eda6377 | |||
| a2cc9b1614 | |||
| 30f918cc15 | |||
| f3d143019b | |||
| 2237618acf | |||
| 550dd0e3a8 | |||
| e9d75a4fe9 | |||
| 1829f9282c | |||
| 08a8068702 | |||
| 3449d81f67 | |||
| f9c2abdc9e | |||
| 3f3b4ccd4f | |||
| df4bf2f6a0 | |||
| a65f8be3c2 | |||
| 9b2efc4552 | |||
| 5a433a51a3 | |||
| 237c1f85dd | |||
| 656d42c4da | |||
| 9f3cadf1e6 | |||
| 1948bdf3f7 | |||
| 39d00cb025 | |||
| cef6136325 | |||
| 29d232c7cc | |||
| 3e2c0132a9 | |||
| f2441a17c8 | |||
| caba629ca1 | |||
| a946097de4 | |||
| ba0ac542c5 | |||
| 173b854168 | |||
| 4c1dc51a6f | |||
| b7d7e70ac5 | |||
| d9bf63bdf4 | |||
| 71643d8cda | |||
| 0fb5c98293 | |||
| e4ccc91d4e | |||
| f3a471fd89 | |||
| 820b971eff | |||
| 5f58fbe6d7 | |||
| 5c5b357b4a | |||
| bcc834fc3e | |||
| 5b818bb318 | |||
| e1efefb7f4 | |||
| 2c0021ad89 | |||
| 9bde204f1d | |||
| 47231e37ef | |||
| 0088b85952 | |||
| 338458a92b | |||
| 3836f13878 | |||
| abe23bf82d | |||
| 6cceb2b873 | |||
| 86430c156c | |||
| 3b57140640 | |||
| f472c67bb2 | |||
| 23033d1f18 | |||
| d7225acd8e | |||
| af3045377a | |||
| f9e2215c49 | |||
| d75a6589f0 | |||
| 47c8e897ce | |||
| 1129d42b48 | |||
| c58072d595 | |||
| b98c4e031d | |||
| 9506b58633 | |||
| 44aa771cc0 | |||
| dad422a430 | |||
| ae83a50fb3 | |||
| 4f4b3aef45 | |||
| 6862f7b9ca | |||
| ad6b19a37c | |||
| bb474f69d8 | |||
| 77353e7f31 | |||
| fba8ea01f5 | |||
| 57917f1656 | |||
| d46a59367f | |||
| 868413839a | |||
| 1225932449 | |||
| f28c2221cc | |||
| 4245423cc1 | |||
| 9beca068b9 | |||
| 079cc2df09 | |||
| 388806f24d | |||
| b0005129c7 | |||
| 1893226cb7 | |||
| 3580240743 | |||
| 7ee0b08647 | |||
| a55d49b754 | |||
| 3d671a6dd4 | |||
| 7711de62fb | |||
| 37712a8fbe | |||
| 99b61089c8 | |||
| c5a6d94110 | |||
| 912085c831 | |||
| 7d85ff76a6 | |||
| 3e49c80799 | |||
| e5aaed2a3f | |||
| ea0dcbdb7c | |||
| 63f82f0ca8 | |||
| 60b9f20469 | |||
| 9f9c11db41 | |||
| 935f3da3ff | |||
| de24a6c1eb | |||
| 3ea8b9298f | |||
| 86684cd246 | |||
| f3d7d5a3cd | |||
| 14d3587858 | |||
| a18051fdd9 | |||
| ac06acbaee | |||
| ae7c58e5b9 | |||
| c15f3214d5 | |||
| a408dd332e | |||
| f0a8201733 | |||
| 127e7441da | |||
| 353268b7cf | |||
| 8eb433518d | |||
| 7d4f5f79e7 | |||
| aa4cf20eae | |||
| 78535d2343 | |||
| e809face7b | |||
| 9fd4726c31 | |||
| 1c3a7748ea | |||
| ce40053a6c | |||
| 9ef6850cc4 | |||
| 3094389a2a | |||
| b812c18e6b | |||
| 6c6a248be8 | |||
| ce6ac7d8c7 | |||
| baa9a4df51 | |||
| 58e03dbc6c | |||
| cfccb83ddd | |||
| b806e3d2ec | |||
| 0725811224 | |||
| 5b1445b381 | |||
| aa088e42d1 | |||
| 7aceceb467 | |||
| 66bb527d22 | |||
| f1d44c166f | |||
| 9c834d6e4d | |||
| 742ccb390a | |||
| 62a74a342c | |||
| 8eb613e50a | |||
| 89b4fbd298 | |||
| 93e64f2210 | |||
| a9a0c046f1 | |||
| d224912bd5 | |||
| 39706cccbe | |||
| 4640c84920 | |||
| af98e3126e | |||
| e063385c47 | |||
| 7a247ff40f | |||
| 5de8c3521f | |||
| b631fb3d05 | |||
| fb4649a3fe | |||
| f00317bead | |||
| 8805ab3ee2 | |||
| ebec978443 | |||
| cfe56d97ea | |||
| 97d2b0146c | |||
| c31666fe2a | |||
| ab35e0f712 | |||
| c85cd07db0 | |||
| f458296a07 | |||
| 8df2f13962 | |||
| cba8f4286d | |||
| 86c7edfd74 | |||
| caadb48e25 | |||
| 3e9fb4757f | |||
| d159739a8b | |||
| f20f61d754 | |||
| 81b740403a | |||
| 3cb8a3d782 | |||
| f8e42cb509 | |||
| d631a5a466 | |||
| 5992929e56 | |||
| 3d640698d8 | |||
| 088177b269 | |||
| 2e03c9c266 | |||
| 65abee1cba | |||
| 1911a2827b | |||
| bb96b920d3 | |||
| 350124a45b | |||
| 5e374218ee | |||
| 9f60957b84 | |||
| 0c0375f8ae | |||
| 77ecd5befc | |||
| a7ac5c2823 | |||
| 44b16a548f | |||
| 9deaae0716 | |||
| 122e378e93 | |||
| 2c24ca1407 | |||
| 04a269f4f8 | |||
| 8999d2ba44 | |||
| 7ac798cef9 | |||
| 67359073ca | |||
| 3edfe19438 | |||
| 9215540015 | |||
| 83cb4cc210 | |||
| d1a14bee5d | |||
| ba3b8f8370 | |||
| 962bbfc6bf | |||
| b00e465deb | |||
| db0870f31f | |||
| 87a6e9693c | |||
| aaacda6e14 | |||
| f9c41a0866 | |||
| fa8aca8789 | |||
| efef4e31dd | |||
| 3973766b84 | |||
| 4d2b1d51e4 | |||
| 8713741782 | |||
| ac6526b731 | |||
| 94897c4eca | |||
| 444cc22633 | |||
| aeea213873 | |||
| 8d31d0c3cc | |||
| 9bd3d84f3d | |||
| 04b66f1965 | |||
| 7c1b9d0a32 | |||
| 02869da279 | |||
| aebfd788c7 | |||
| 26d82cf55d | |||
| d9335f6a95 | |||
| 0e7cc36567 | |||
| e57663c937 | |||
| 23433fe2dc | |||
| fefb9f4428 | |||
| 68c4b8a60f | |||
| 33b6f0f3a4 | |||
| ca0ba55050 | |||
| 236618f87b | |||
| f5ea52a2b8 | |||
| 6a6daad739 | |||
| 4724e5fec3 | |||
| d3d1b0cbcc | |||
| 20aa6cb764 | |||
| a41bb7c07a | |||
| 53ccae09cc | |||
| 869251e590 | |||
| 45f1af2bde | |||
| 15d25242be | |||
| 22509ab2d4 | |||
| 796e1ad22a | |||
| acfcf2f1d1 | |||
| ca46387b64 | |||
| fd79b81918 | |||
| 9ace148917 | |||
| a85c9f4898 | |||
| fadcd1fac5 | |||
| 1a4445f510 | |||
| fc824ff6d4 | |||
| 2c690425c9 | |||
| ee71f0f870 | |||
| e8650c1b8e | |||
| cef7718468 | |||
| 895154bcb2 | |||
| f421b74c0f | |||
| 90edc3b0a5 | |||
| f1d602029c | |||
| 10a889c482 | |||
| b7f50b2fb6 | |||
| 2ee6a76464 | |||
| f0d3e9a5c8 | |||
| 7c284cc5bc | |||
| 7b96144716 | |||
| 81c7cb6527 | |||
| 186d3ce9fb | |||
| e7edb181dc | |||
| ef8b3e6195 | |||
| 7f9ded7642 | |||
| 34b06ca587 | |||
| 4d845608b8 | |||
| eaf32c83bf | |||
| 808e6b9b20 | |||
| 7dd72e7328 | |||
| f8270483e1 | |||
| f17babfe8a | |||
| f65d5ad7a9 | |||
| 0d78f10161 | |||
| 7d5b61ce01 | |||
| b48933b096 | |||
| fd1dfd7d65 | |||
| be56f2c524 | |||
| d31c10a01e | |||
| c04e57399a | |||
| 6c090f6193 | |||
| 5ca45bce37 | |||
| 729327a078 | |||
| ea76845ecb | |||
| 5506aed190 | |||
| 43366d1c6a | |||
| f35f4b9fad | |||
| c4b4fcc17e | |||
| fbf132d1d1 | |||
| e274c195af | |||
| fd28dc5644 | |||
| 5aa3de194c | |||
| 9400199b80 | |||
| 200d344dee | |||
| 094edcd32e | |||
| a005a044da | |||
| ae315eecb9 | |||
| dcb0ca5d14 | |||
| 07b729d5d6 | |||
| cd4599b447 | |||
| b2ea5eae5e | |||
| 29ff1f02e9 | |||
| d840a100a7 | |||
| 95bfa196fd | |||
| aceb8ce3a8 | |||
| 33e889907e | |||
| 61537200c0 | |||
| 080f5c94bd | |||
| 7207c03c72 | |||
| cf9f27db54 | |||
| 0a2b81b128 | |||
| 05c15c8ba7 | |||
| d768dae402 | |||
| d580c47504 | |||
| 7b7ded566c | |||
| d9427b1e6f | |||
| da55d9067c | |||
| e5702a716f | |||
| 2dd8d7e8b1 | |||
| 168e2c43d0 | |||
| 638c1cb339 | |||
| 6a430eb834 | |||
| 3c82b48b1f | |||
| 72a341a37f | |||
| 79d5353cfd | |||
| 98efce4b0d | |||
| c9c26d8071 | |||
| 0e68f812b5 | |||
| 2752837839 | |||
| a627cd5b65 | |||
| 361dcb2a1f | |||
| 5082f5a813 | |||
| 3d2008c70b | |||
| a685b812d9 | |||
| 3b70f83c7d | |||
| a28b924f94 | |||
| 636269f6af | |||
| 826ca42d83 | |||
| 620b21bfce | |||
| 52dc7658da | |||
| 06621eb3b7 | |||
| 3b9ee2e9f3 | |||
| 6ae16c9895 | |||
| aa1100817a | |||
| 725c8b57ae | |||
| 00f3af78e3 | |||
| 3d3e6996b0 | |||
| 47bb749ce9 | |||
| ba72d25867 | |||
| 8e82249f65 | |||
| dff07d020c | |||
| 0f98d78a67 | |||
| c2ea6a38b5 | |||
| ccc0d7452a | |||
| 386eabb932 | |||
| 4ee2013169 | |||
| d892f3ba4a | |||
| 61dd488b76 | |||
| 4cae4ba9d5 | |||
| 07a056441a | |||
| 254953611e | |||
| 5608460901 | |||
| 3b23200b85 | |||
| 1c5cd35372 | |||
| e9caf5a981 | |||
| de8419cc8b | |||
| f220848896 |
12
.github/workflows/analyze_codeql.yml
vendored
@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@ -71,7 +71,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@ -90,7 +90,7 @@ jobs:
|
||||
cmake --build . --config $BUILD_TYPE
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
upload: false
|
||||
@ -99,7 +99,7 @@ jobs:
|
||||
# Filter out rules with low severity or high false positve rate
|
||||
# Also filter out warnings in third-party code
|
||||
- name: Filter out unwanted errors and warnings
|
||||
uses: advanced-security/filter-sarif@v1
|
||||
uses: advanced-security/filter-sarif@v1.1
|
||||
with:
|
||||
patterns: |
|
||||
-**:cpp/path-injection
|
||||
@ -121,14 +121,14 @@ jobs:
|
||||
output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
|
||||
|
||||
- name: Upload CodeQL results to code scanning
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
with:
|
||||
sarif_file: ${{ steps.step1.outputs.sarif-output }}
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
- name: Upload CodeQL results as an artifact
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: codeql-results
|
||||
path: ${{ steps.step1.outputs.sarif-output }}
|
||||
|
||||
6
.github/workflows/build_android.yml
vendored
@ -21,7 +21,7 @@ permissions:
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write # for actions/upload-release-asset to upload release asset
|
||||
contents: write # Required for actions/upload-release-asset to upload release asset
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@ -82,7 +82,7 @@ jobs:
|
||||
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ env.RELEASE_NAME }}
|
||||
path: |
|
||||
@ -90,7 +90,7 @@ jobs:
|
||||
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||
|
||||
- name: Upload Artifact to Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||
env:
|
||||
|
||||
4
.github/workflows/build_cmake.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Create Build Environment
|
||||
# Some projects don't allow in-source building, so create a separate build directory
|
||||
@ -75,7 +75,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Create Build Environment
|
||||
# Some projects don't allow in-source building, so create a separate build directory
|
||||
|
||||
2
.github/workflows/build_examples_linux.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Setup Environment
|
||||
run: |
|
||||
|
||||
4
.github/workflows/build_examples_windows.yml
vendored
@ -22,10 +22,10 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Build Library (MSVC16)
|
||||
run: |
|
||||
|
||||
6
.github/workflows/build_linux.yml
vendored
@ -21,7 +21,7 @@ permissions:
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write # for actions/upload-release-asset to upload release asset
|
||||
contents: write # Required for actions/upload-release-asset to upload release asset
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 1
|
||||
@ -112,7 +112,7 @@ jobs:
|
||||
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ env.RELEASE_NAME }}
|
||||
path: |
|
||||
@ -120,7 +120,7 @@ jobs:
|
||||
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||
|
||||
- name: Upload Artifact to Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||
env:
|
||||
|
||||
6
.github/workflows/build_macos.yml
vendored
@ -21,7 +21,7 @@ permissions:
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write # for actions/upload-release-asset to upload release asset
|
||||
contents: write # Required for actions/upload-release-asset to upload release asset
|
||||
runs-on: macos-latest
|
||||
|
||||
env:
|
||||
@ -99,7 +99,7 @@ jobs:
|
||||
tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ env.RELEASE_NAME }}
|
||||
path: |
|
||||
@ -107,7 +107,7 @@ jobs:
|
||||
!./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||
|
||||
- name: Upload Artifact to Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: ./build/${{ env.RELEASE_NAME }}.tar.gz
|
||||
env:
|
||||
|
||||
6
.github/workflows/build_webassembly.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Setup emsdk
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
uses: emscripten-core/setup-emsdk@v15
|
||||
with:
|
||||
version: 5.0.3
|
||||
actions-cache-folder: 'emsdk-cache'
|
||||
@ -69,7 +69,7 @@ jobs:
|
||||
shell: cmd
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ env.RELEASE_NAME }}
|
||||
path: |
|
||||
@ -77,7 +77,7 @@ jobs:
|
||||
!./build/${{ env.RELEASE_NAME }}.zip
|
||||
|
||||
- name: Upload Artifact to Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: ./build/${{ env.RELEASE_NAME }}.zip
|
||||
env:
|
||||
|
||||
8
.github/workflows/build_windows.yml
vendored
@ -21,7 +21,7 @@ permissions:
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write # for actions/upload-release-asset to upload release asset
|
||||
contents: write # Required for actions/upload-release-asset to upload release asset
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@ -81,7 +81,7 @@ jobs:
|
||||
|
||||
# Setup MSBuild.exe path if required
|
||||
- name: Setup MSBuild
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
if: matrix.compiler == 'msvc16'
|
||||
|
||||
- name: Build Library (MinGW-w64 32bit)
|
||||
@ -140,7 +140,7 @@ jobs:
|
||||
shell: cmd
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ env.RELEASE_NAME }}
|
||||
path: |
|
||||
@ -148,7 +148,7 @@ jobs:
|
||||
!./build/${{ env.RELEASE_NAME }}.zip
|
||||
|
||||
- name: Upload Artifact to Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: ./build/${{ env.RELEASE_NAME }}.zip
|
||||
env:
|
||||
|
||||
81
.github/workflows/clang_tidy.yml
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
name: Clang Tidy Lints
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: clang-tidy-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
clang-tidy:
|
||||
name: C lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install clang-tidy 19
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes clang-tidy-19
|
||||
|
||||
- name: Run clang-tidy
|
||||
shell: bash
|
||||
run: |
|
||||
checks='-*,
|
||||
bugprone-assignment-in-if-condition,
|
||||
bugprone-infinite-loop,
|
||||
bugprone-misplaced-widening-cast,
|
||||
bugprone-multiple-statement-macro,
|
||||
bugprone-suspicious-memory-comparison,
|
||||
bugprone-suspicious-memset-usage,
|
||||
readability-duplicate-include,
|
||||
readability-redundant-casting,
|
||||
readability-simplify-boolean-expr'
|
||||
|
||||
lint_log="$(mktemp)"
|
||||
filtered_log="$(mktemp)"
|
||||
lint_pattern='\[(bugprone|readability)-[^]]+\]'
|
||||
|
||||
echo "Using clang-tidy:"
|
||||
clang-tidy-19 --version
|
||||
|
||||
echo
|
||||
echo "Running clang-tidy..."
|
||||
|
||||
# Capture everything silently. Do not use tee here.
|
||||
find src \
|
||||
-path 'src/external' -prune \
|
||||
-o -type f -name '*.c' -exec \
|
||||
clang-tidy-19 \
|
||||
--quiet \
|
||||
--checks="$checks" \
|
||||
--header-filter='.*' \
|
||||
--exclude-header-filter='(^|.*/)external/.*' \
|
||||
{} -- \
|
||||
-std=c11 \
|
||||
-Isrc \
|
||||
-isystem src/external \
|
||||
\; >"$lint_log" 2>&1 || true
|
||||
|
||||
# Retain only selected lint warnings, then remove any remaining
|
||||
# diagnostics whose path passes through an external directory.
|
||||
grep -E "$lint_pattern" "$lint_log" |
|
||||
grep -Ev '(^|/)([^/]+/\.\./)*external/' \
|
||||
>"$filtered_log" || true
|
||||
|
||||
if [[ -s "$filtered_log" ]]; then
|
||||
echo "clang-tidy found the following lint violations:"
|
||||
echo
|
||||
cat "$filtered_log"
|
||||
echo
|
||||
echo "::error::clang-tidy found lint violations."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "clang-tidy found no selected lint violations."
|
||||
2
.github/workflows/parse_api.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Update parse files
|
||||
working-directory: tools/rlparser
|
||||
|
||||
4
.github/workflows/update_examples.yml
vendored
@ -15,10 +15,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Setup emsdk
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
uses: emscripten-core/setup-emsdk@v15
|
||||
with:
|
||||
version: 'latest'
|
||||
actions-cache-folder: 'emsdk-cache'
|
||||
|
||||
6
.gitignore
vendored
@ -65,7 +65,7 @@ src/external/SDL3
|
||||
# Emscripten
|
||||
emsdk
|
||||
|
||||
# Ignore wasm data in examples/
|
||||
# Ignore binaries generated in examples/
|
||||
examples/**/*
|
||||
!examples/**/*.*
|
||||
!examples/**/*/
|
||||
@ -125,8 +125,8 @@ build-*/
|
||||
docgen_tmp/
|
||||
|
||||
# Tools stuff
|
||||
tools/parser/rlparser.exe
|
||||
tools/parser/rlparser
|
||||
tools/rlparser/rlparser.exe
|
||||
tools/rlparser/rlparser
|
||||
tools/rexm/rexm.exe
|
||||
tools/rexm/rexm
|
||||
|
||||
|
||||
363
BINDINGS.md
@ -1,187 +1,218 @@
|
||||
# raylib bindings and wrappers
|
||||
|
||||
Some people ported raylib to other languages in the form of bindings or wrappers to the library. Here is a list with all the ports available. Feel free to send a PR if you know of any binding/wrapper not in this list.
|
||||
Some people ported raylib to other languages in the form of bindings or wrappers to the library. Here is a list with all the ports available. Feel free to send a PR if you know of any binding/wrapper not in this list or if it had been updated/archived.
|
||||
|
||||
# Recommendations for binding authors.
|
||||
This is a set of recomendations and guidelines for binding authors, meant to help your binding be as useful as possible to your users.
|
||||
|
||||
* Binding should be reasonably up to date with the last release, out of date bindings may be removed from bindings.md
|
||||
* Binding should expose all of raylib's API. This is to ensure compatibility with all raylib features, and allow your users to do everything in the target language they can do in C raylib.
|
||||
* raylib.h
|
||||
* raymath.h
|
||||
* rcamera.h
|
||||
* rlgl.h
|
||||
* rgestures.h
|
||||
* Bindings should expose the base API in order to match the C examples when possible.
|
||||
* Bindings that expose additional 'high level' functions to make the binding more native to the host language, should also include the base C style API in addition to those other functions. This is requested in order to make it easier for people to understand the raylib API independent of the language being used.
|
||||
* Bindings should have clear usage and setup instructions. Examples in the host language are highly recommended. You want your users to be able to get started right away.
|
||||
* If a binding exists for a language, before making a new one, binding authors should try to work together on maintaining a single binding for a language, this is requested in order to prevent fragmentation and confusion for users.
|
||||
* Instructions on how to build for web are highly recomeneed if the langauge supports it. This allows your bindings to be used for game jams :)
|
||||
|
||||
### Language Bindings
|
||||
|
||||
| Name | raylib Version | Language | License |
|
||||
| :--------------------------------------------------------------------------------------- | :--------------: | :------------------------------------------------------------------: | :------------------: |
|
||||
| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
|
||||
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **5.5** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
|
||||
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.5** | [Beef](https://www.beeflang.org) | MIT |
|
||||
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
|
||||
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib55.c3l) | **5.5** | [C3](https://c3-lang.org) | MIT |
|
||||
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
||||
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
|
||||
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
|
||||
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
|
||||
| [Raylib-cs.BleedingEdge](https://github.com/danilwhale/Raylib-cs.BleedingEdge) | **5.6-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
||||
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
|
||||
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
|
||||
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
|
||||
| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 |
|
||||
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
|
||||
| [chicken-raylib](https://github.com/meowstr/chicken-raylib) | 5.5 | [CHICKEN Scheme](https://wiki.call-cc.org) | MIT |
|
||||
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
|
||||
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 4.6-dev (5e1a81) | [Crystal](https://crystal-lang.org) | Apache-2.0 |
|
||||
| [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
|
||||
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
|
||||
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
|
||||
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 |
|
||||
| [raylib-d](https://github.com/schveiguy/raylib-d) | **5.5** | [D](https://dlang.org) | Zlib |
|
||||
| [DenoRaylib550](https://github.com/JJLDonley/DenoRaylib550) | **5.5** | [Deno](https://deno.land) | MIT |
|
||||
| [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 |
|
||||
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
|
||||
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 5.5 | [Factor](https://factorcode.org) | BSD |
|
||||
| [raylib4fb](https://github.com/mudhairless/raylib4fb) | **5.5** | [FreeBASIC](https://www.freebasic.net) | Zlib |
|
||||
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
|
||||
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
|
||||
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC |
|
||||
| [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib |
|
||||
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
|
||||
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) | **???** |
|
||||
| [h-raylib](https://github.com/Anut-py/h-raylib) | **5.5-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
|
||||
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 4.2 | [Haxe](https://haxe.org) | Zlib |
|
||||
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.5 | [Harbour](https://harbour.github.io) | MIT |
|
||||
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
|
||||
| [jaylib](https://github.com/electronstudio/jaylib/) | **5.5** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE |
|
||||
| [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.0 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib |
|
||||
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
|
||||
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) | **???** |
|
||||
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
|
||||
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.0 | [Lua](http://www.lua.org) | ISC |
|
||||
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
||||
| [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
|
||||
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
|
||||
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | **5.5** | [nelua](https://nelua.io) | Zlib |
|
||||
| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 5.6-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib |
|
||||
| [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) | MIT |
|
||||
| [node-raylib](https://github.com/RobLoach/node-raylib) | 4.5 | [Node.js](https://nodejs.org/en) | Zlib |
|
||||
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **5.5** | [Odin](https://odin-lang.org) | Zlib |
|
||||
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
|
||||
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **5.0** | [OCaml](https://ocaml.org) | MIT |
|
||||
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
|
||||
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **5.5** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal)/[Delphi](https://en.wikipedia.org/wiki/Delphi_(software)) | Zlib |
|
||||
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
|
||||
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) | Zlib |
|
||||
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **5.5** | [Python](https://www.python.org) | EPL-2.0 |
|
||||
| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 5.5 | [Python](https://www.python.org) | MIT |
|
||||
| [raylib-py](https://github.com/overdev/raylib-py) | 5.5 | [Python](https://www.python.org) | MIT |
|
||||
| [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT |
|
||||
| [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 5.1-dev | [pocketpy](https://pocketpy.dev) | MIT |
|
||||
| [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
|
||||
| [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
|
||||
| [raylibr](https://github.com/jeroenjanssens/raylibr) | 4.0 | [R](https://www.r-project.org) | MIT |
|
||||
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
|
||||
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **5.5** | [Rust](https://www.rust-lang.org) | Zlib |
|
||||
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
|
||||
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | **???** |
|
||||
| [racket-raylib](https://github.com/eutro/racket-raylib) | **5.5** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
|
||||
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
|
||||
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
|
||||
| [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **5.5** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 |
|
||||
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
|
||||
| [raylib-v](https://github.com/vlang/raylib) | 5.5 | [V](https://vlang.io) | MIT/Unlicense |
|
||||
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
|
||||
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **5.0** | [Vala](https://vala.dev) | Zlib |
|
||||
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** |[Wave](http://wave-lang.dev) | Zlib |
|
||||
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
|
||||
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **5.6-dev** | [Zig](https://ziglang.org) | MIT |
|
||||
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
|
||||
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
|
||||
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
|
||||
| [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD |
|
||||
| [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
|
||||
| [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT |
|
||||
| [rayjule](https://github.com/SabeDoesThings/rayjule) | **5.5** | [Jule](https://jule.dev/) | MIT |
|
||||
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
|
||||
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.5-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
|
||||
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
|
||||
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **5.0** | [Dyalog APL](https://www.dyalog.com/) | MIT |
|
||||
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **5.5** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
|
||||
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
|
||||
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
|
||||
| [Target](https://github.com/FinnDemonCat/Target/tree/main/libs/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
|
||||
| Name | raylib Version | Language | License |
|
||||
| :--------------------------------------------------------------------------------------: | :--------------: | :---------------------------------------------------------------------: | :------------------: |
|
||||
| [raylib](https://github.com/raysan5/raylib) | **6.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib |
|
||||
| [raylib-ada](https://github.com/Fabien-Chouteau/raylib-ada) | **6.0** | [Ada](https://en.wikipedia.org/wiki/Ada_(programming_language)) | MIT |
|
||||
| [raylib-asm](https://github.com/gAndy50/ASMRay) | **6.0** | [Assembly (x86)](https://en.wikipedia.org/wiki/X86_assembly_language) | Zlib |
|
||||
| [raylib-beef](https://github.com/Starpelly/raylib-beef) | **auto** | [Beef](https://www.beeflang.org) | MIT |
|
||||
| [raybit](https://github.com/Alex-Velez/raybit) | **5.0** | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT |
|
||||
| [raylib-c3](https://github.com/c3lang/vendor/tree/main/libraries/raylib6.c3l) | **6** | [C3](https://c3-lang.org) | MIT |
|
||||
| [raylib-cs](https://github.com/raylib-cs/raylib-cs) | **6.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
||||
| [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 |
|
||||
| [Raylib-CSharp](https://github.com/MrScautHD/Raylib-CSharp) | **5.5** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MIT |
|
||||
| [Raylib-cs.BleedingEdge](https://github.com/danilwhale/Raylib-cs.BleedingEdge) | **5.6-dev** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib |
|
||||
| [cl-raylib](https://github.com/longlene/cl-raylib) | 4.0 | [Common Lisp](https://common-lisp.net) | MIT |
|
||||
| [claylib/wrap](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
|
||||
| [claw-raylib](https://github.com/bohonghuang/claw-raylib) | **auto** | [Common Lisp](https://common-lisp.net) | Apache-2.0 |
|
||||
| [raylib](https://github.com/fosskers/raylib) | 5.5 | [Common Lisp](https://common-lisp.net) | MPL-2.0 |
|
||||
| [chez-raylib](https://github.com/Yunoinsky/chez-raylib) | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme) | GPLv3 |
|
||||
| [chicken-raylib](https://github.com/meowstr/chicken-raylib) | 5.5 | [CHICKEN Scheme](https://wiki.call-cc.org) | MIT |
|
||||
| [CLIPSraylib](https://github.com/mrryanjohnston/CLIPSraylib) | **auto** | [CLIPS](https://www.clipsrules.net/) | MIT |
|
||||
| [raylib-cr](https://github.com/sol-vin/raylib-cr) | 6.0 | [Crystal](https://crystal-lang.org) | Apache-2.0 |
|
||||
| [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT |
|
||||
| [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT |
|
||||
| [raylib_dart](https://pub.dev/packages/raylib_dart) | 6.0 | [Dart](https://dart.dev) | MIT |
|
||||
| [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 |
|
||||
| [raylib-d](https://github.com/schveiguy/raylib-d) | **6.0** | [D](https://dlang.org) | Zlib |
|
||||
| [Deno-Raylib](https://github.com/JJLDonley/Deno-Raylib) | **6.0** | [Deno / TS](https://deno.land) | MIT |
|
||||
| [rayex](https://github.com/shiryel/rayex) | 5.5 | [elixir](https://elixir-lang.org) | Apache-2.0 |
|
||||
| [raylib-elfscript](https://github.com/ohmtal/raylib-elfscript) | 6.0 | [ElfScript](https://github.com/ohmtal/ElfScript) | MIT |
|
||||
| [raylib-elle](https://github.com/acquitelol/elle/blob/rewrite/std/raylib.le) | **5.5** | [Elle](https://github.com/acquitelol/elle) | GPL-3.0 |
|
||||
| [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 6.0 | [Factor](https://factorcode.org) | BSD |
|
||||
| [raystar](https://github.com/RobertFlexx/raystar) | **6.0** | [F*](https://www.fstar-lang.org/) | EPL-2.0 |
|
||||
| [raylib4fb](https://codeberg.org/mudhairless/raylib4fb) | **6.0** | [FreeBASIC](https://www.freebasic.net) | Zlib |
|
||||
| [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT |
|
||||
| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib |
|
||||
| [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **6.0** | [Fortran](https://fortran-lang.org) | ISC |
|
||||
| [raylib-go](https://github.com/gen2brain/raylib-go) | **6.0** | [Go](https://golang.org) | Zlib |
|
||||
| [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib |
|
||||
| [h-raylib](https://github.com/Anut-py/h-raylib) | **6.1-dev** | [Haskell](https://haskell.org) | Apache-2.0 |
|
||||
| [raylib-hx](https://github.com/foreignsasquatch/raylib-hx) | 5.5 | [Haxe](https://haxe.org) | Zlib |
|
||||
| [jaylib](https://github.com/janet-lang/jaylib) | **5.0** | [Janet](https://janet-lang.org) | MIT |
|
||||
| [jaylib](https://github.com/electronstudio/jaylib/) | **6.0** | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | GPLv3+CE |
|
||||
| [raylib-j](https://github.com/CreedVI/Raylib-J) | 4.2 | [Java](https://en.wikipedia.org/wiki/Java_(programming_language)) | Zlib |
|
||||
| [Raylib.jl](https://github.com/chengchingwen/Raylib.jl) | 4.2 | [Julia](https://julialang.org) | Zlib |
|
||||
| [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib |
|
||||
| [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC |
|
||||
| [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 6.0 | [Lua](http://www.lua.org) | ISC |
|
||||
| [ReiLua](https://github.com/nullstare/ReiLua) | 6.0 | [Lua](http://www.lua.org) | MIT |
|
||||
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib |
|
||||
| [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||
| [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT |
|
||||
| [raylib-matte](https://github.com/jcorks/raylib-matte) | 4.6-dev | [Matte](https://github.com/jcorks/matte) | **???** |
|
||||
| [raylib_mojo](https://github.com/willGuimont/raylib_mojo) | **6.0** | [Mojo](https://www.modular.com/mojo) | ZLib |
|
||||
| [raymojo](https://github.com/RobertFlexx/raymojo) | **6.0** | [Mojo](https://www.modular.com/mojo) | GPLv3 |
|
||||
| [raymod](https://github.com/RobertFlexx/raymod) | **6.0** | [Modula-2](https://en.wikipedia.org/wiki/Modula-2) / [Modula-3](https://en.wikipedia.org/wiki/Modula-3) | Apache-2.0 |
|
||||
| [Raylib.nelua](https://github.com/AuzFox/Raylib.nelua) | 6.1-dev | [nelua](https://nelua.io) | Zlib |
|
||||
| [raylib-bindings](https://github.com/vaiorabbit/raylib-bindings) | 6.1-dev | [Ruby](https://www.ruby-lang.org/en) | Zlib |
|
||||
| [node-raylib](https://github.com/RobLoach/node-raylib) | 5.5 | [Node.js](https://nodejs.org/en) | Zlib |
|
||||
| [raylib-odin](https://github.com/odin-lang/Odin/tree/master/vendor/raylib) | **6.0** | [Odin](https://odin-lang.org) | Zlib |
|
||||
| [raylib_odin_bindings](https://github.com/Deathbat2190/raylib_odin_bindings) | 4.0-dev | [Odin](https://odin-lang.org) | MIT |
|
||||
| [raylib-ocaml](https://github.com/tjammer/raylib-ocaml) | **6.0** | [OCaml](https://ocaml.org) | MIT |
|
||||
| [TurboRaylib](https://github.com/turborium/TurboRaylib) | 4.5 | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | MIT |
|
||||
| [Rayberon](https://github.com/RobertFlexx/Rayberon) | **6.0** | [Oberon-2](https://en.wikipedia.org/wiki/Oberon-2) | MIT |
|
||||
| [EuRaylib](https://github.com/gAndy50/EuRaylib6) | **6.0** | [openEuphoria](https://openeuphoria.org/) | Zlib |
|
||||
| [Ray4Laz](https://github.com/GuvaCode/Ray4Laz) | **6.0** | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
|
||||
| [Raylib.4.0.Pascal](https://github.com/sysrpl/Raylib.4.0.Pascal) | 4.0 | [Free Pascal](https://en.wikipedia.org/wiki/Free_Pascal) | Zlib |
|
||||
| [raylib-python-cffi](https://github.com/electronstudio/raylib-python-cffi) | **6.0** | [Python](https://www.python.org) | EPL-2.0 |
|
||||
| [raylibpyctbg](https://github.com/overdev/raylibpyctbg) | 5.5 | [Python](https://www.python.org) | MIT |
|
||||
| [raylib-py](https://github.com/overdev/raylib-py) | **6.0** | [Python](https://www.python.org) | MIT |
|
||||
| [raylib-python-ctypes](https://github.com/sDos280/raylib-python-ctypes) | 4.6-dev | [Python](https://www.python.org) | MIT |
|
||||
| [raylib-pkpy-bindings](https://github.com/blueloveTH/pkpy-bindings) | 5.5 | [pocketpy](https://pocketpy.dev) | MIT |
|
||||
| [raylib-php](https://github.com/joseph-montanez/raylib-php) | 4.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib |
|
||||
| [raylibr](https://github.com/jeroenjanssens/raylibr) | auto | [R](https://www.r-project.org) | MIT |
|
||||
| [raylib-ffi](https://github.com/ewpratten/raylib-ffi) | 5.5 | [Rust](https://www.rust-lang.org) | GPLv3 |
|
||||
| [raylib-rs](https://github.com/raylib-rs/raylib-rs) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
|
||||
| [sola-raylib](https://github.com/brettchalupa/sola-raylib) | **6.0** | [Rust](https://www.rust-lang.org) | Zlib |
|
||||
| [raylib-ruby](https://github.com/wilsonsilva/raylib-ruby) | 4.5 | [Ruby](https://www.ruby-lang.org) | Zlib |
|
||||
| [racket-raylib](https://github.com/eutro/racket-raylib) | **6.0** | [Racket](https://racket-lang.org) | MIT/Apache-2.0 |
|
||||
| [raylib-swift](https://github.com/STREGAsGate/Raylib) | 4.0 | [Swift](https://swift.org) | MIT |
|
||||
| [raylib-scopes](https://github.com/salotz/raylib-scopes) | auto | [Scopes](http://scopes.rocks) | MIT |
|
||||
| [raylib-SmallBASIC](https://github.com/smallbasic/smallbasic.plugins/tree/master/raylib) | **6.0** | [SmallBASIC](https://github.com/smallbasic/SmallBASIC) | GPLv3 |
|
||||
| [raylib-solod](https://github.com/solod-dev/raylib) | 6.0 | [Solod](https://solod.dev) | BSD-3-Clause |
|
||||
| [rayscal](https://github.com/RobertFlexx/rayscal) | **6.0** | [Scala Native](https://scala-native.org) | MIT |
|
||||
| [raylib-umka](https://github.com/robloach/raylib-umka) | 4.5 | [Umka](https://github.com/vtereshkov/umka-lang) | Zlib |
|
||||
| [raylib-v](https://github.com/vlang/raylib) | auto | [V](https://vlang.io) | MIT/Unlicense |
|
||||
| [raylib.v](https://github.com/irishgreencitrus/raylib.v) | 4.2 | [V](https://vlang.io) | Zlib |
|
||||
| [raylib-vapi](https://github.com/lxmcf/raylib-vapi) | **6.0** | [Vala](https://vala.dev) | Zlib |
|
||||
| [raylib-wave](https://github.com/wavefnd/raylib-wave) | **auto** | [Wave](http://wave-lang.dev) | Zlib |
|
||||
| [raylib-wren](https://github.com/TSnake41/raylib-wren) | 4.5 | [Wren](http://wren.io) | ISC |
|
||||
| [raylib-zig](https://github.com/raylib-zig/raylib-zig) | **6.0** | [Zig](https://ziglang.org) | MIT |
|
||||
| [raylib.zig](https://github.com/ryupold/raylib.zig) | **5.1-dev** | [Zig](https://ziglang.org) | MIT |
|
||||
| [raylib-zig-bindings](https://github.com/L-Briand/raylib-zig-bindings) | **5.0** | [Zig](https://ziglang.org) | Zlib |
|
||||
| [hare-raylib](https://git.sr.ht/~evantj/hare-raylib) | **auto** | [Hare](https://harelang.org) | Zlib |
|
||||
| [raylib-sunder](https://github.com/ashn-dot-dev/raylib-sunder) | **auto** | [Sunder](https://github.com/ashn-dot-dev/sunder) | 0BSD |
|
||||
| [raylib-bqn](https://github.com/Brian-ED/raylib-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
|
||||
| [rayjs](https://github.com/mode777/rayjs) | 4.6-dev | [QuickJS](https://bellard.org/quickjs) | MIT |
|
||||
| [raylib-raku](https://github.com/vushu/raylib-raku) | **auto** | [Raku](https://www.raku.org) | Artistic License 2.0 |
|
||||
| [Raylib.lean](https://github.com/KislyjKisel/Raylib.lean) | **5.6-dev** | [Lean4](https://lean-lang.org) | BSD-3-Clause |
|
||||
| [raylib-cobol](https://codeberg.org/glowiak/raylib-cobol) | **auto** | [COBOL](https://gnucobol.sourceforge.io) | Public domain |
|
||||
| [raylib-apl](https://github.com/Brian-ED/raylib-apl) | **auto** | [Dyalog APL](https://www.dyalog.com/) | MIT |
|
||||
| [raylib-jai](https://github.com/ahmedqarmout2/raylib-jai) | **6.0** | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) | MIT |
|
||||
| [fnl-raylib](https://github.com/0riginaln0/fnl-raylib) | **5.5** | [Fennel](https://fennel-lang.org/) | MIT |
|
||||
| [Rayua](https://github.com/uiua-lang/rayua) | **5.5** | [Uiua](https://www.uiua.org/) | **???** |
|
||||
| [Target](https://github.com/FinnDemonCat/Target/tree/main/lib/raylib) | **5.5** | [Dart](https://dart.dev/) | Apache-2.0 license |
|
||||
| [mach-raylib](https://github.com/angluca/mach-raylib) | **6.x-dev** | [Mach](https://machlang.org/) | MIT |
|
||||
| [gcl native raylib module](https://github.com/gnuchanos/GnuchanOS/tree/main/language) | **6.0** | [gclang](https://github.com/gnuchanos/GnuchanOS/tree/main/language) | GPLv3 |
|
||||
|
||||
|
||||
### Utility Wrapers
|
||||
### Utility Wrappers
|
||||
|
||||
These are utility wrappers for specific languages, they are not required to use raylib in the language but may adapt the raylib API to be more inline with the language's paradigm.
|
||||
| Name | raylib Version | Language | License |
|
||||
| ---------------------------------------------------- | :------------: | :------------------------------------------: | :-----: |
|
||||
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **5.5** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
|
||||
| [raylib-cpp](https://github.com/robloach/raylib-cpp) | **6.0** | [C++](https://en.wikipedia.org/wiki/C%2B%2B) | Zlib |
|
||||
| [claylib](https://github.com/defun-games/claylib) | 4.5 | [Common Lisp](https://common-lisp.net) | Zlib |
|
||||
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **5.0** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
|
||||
| [rayed-bqn](https://github.com/Brian-ED/rayed-bqn) | **auto** | [BQN](https://mlochbaum.github.io/BQN) | MIT |
|
||||
| [DOOR](https://github.com/RealDoigt/DOOR) | 4.0 | [D](https://dlang.org) | MIT |
|
||||
| [Iris](https://github.com/Marcos-cat/iris) | **5.5** | [Uiua](https://www.uiua.org/) | MIT |
|
||||
|
||||
### Older or Unmaintained Language Bindings
|
||||
|
||||
These are older raylib bindings that are more than 2 versions old or have not been maintained.
|
||||
| Name | raylib Version | Language |
|
||||
| ---------------------------------------------------------------------------------- | :------------: | :---------------------------------------------------------------------: |
|
||||
| [raylib-cppsharp](https://github.com/phxvyper/raylib-cppsharp) | 2.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
|
||||
| [RaylibFS](https://github.com/dallinbeutler/RaylibFS) | 2.5 | [F#](https://fsharp.org) |
|
||||
| [raylib\*d](https://github.com/Sepheus/raylib_d) | 2.5 | [D](https://dlang.org) |
|
||||
| [bindbc-raylib](https://github.com/o3o/bindbc-raylib) | 3.0 | [D](https://dlang.org) |
|
||||
| [go-raylib](https://github.com/chunqian/go-raylib) | 3.5 | [Go](https://golang.org) |
|
||||
| [raylib-goplus](https://github.com/Lachee/raylib-goplus) | 2.6-dev | [Go](https://golang.org) |
|
||||
| [ray-go](https://github.com/hecate-tech/ray-go) | 2.6-dev | [Go](https://golang.org) |
|
||||
| [raylib-luamore](https://github.com/HDPLocust/raylib-luamore) | 3.0 | [Lua](http://www.lua.org) |
|
||||
| [LuaJIT-Raylib](https://github.com/Bambofy/LuaJIT-Raylib) | 2.6 | [Lua](http://www.lua.org) |
|
||||
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 2.5 | [Lua](http://www.lua.org) |
|
||||
| [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) | 2.0 | [Lua](http://www.lua.org) |
|
||||
| [raylib-lua](https://github.com/raysan5/raylib-lua) | 1.7 | [Lua](http://www.lua.org) |
|
||||
| [raylib-nelua](https://github.com/Andre-LA/raylib-nelua) | 3.0 | [Nelua](https://nelua.io) |
|
||||
| [raylib-nim](https://github.com/Skrylar/raylib-nim) | 2.0 | [Nim](https://nim-lang.org) |
|
||||
| [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) | 1.7 | [Nim](https://nim-lang.org) |
|
||||
| [nim-raylib](https://github.com/tomc1998/nim-raylib) | 3.1-dev | [Nim](https://nim-lang.org) |
|
||||
| [raylib-Forever](https://github.com/Guevara-chan/Raylib-Forever) | auto | [Nim](https://nim-lang.org) |
|
||||
| [NimraylibNow!](https://github.com/greenfork/nimraylib_now) | 4.2 | [Nim](https://nim-lang.org) |
|
||||
| [raylib-haskell](https://github.com/DevJac/raylib-haskell) | 2.0 | [Haskell](https://www.haskell.org) |
|
||||
| [raylib-cr](https://github.com/AregevDev/raylib-cr) | 2.5-dev | [Crystal](https://crystal-lang.org) |
|
||||
| [raylib.cr](https://github.com/sam0x17/raylib.cr) | 2.0 | [Crystal](https://crystal-lang.org) |
|
||||
| [cray](https://gitlab.com/Zatherz/cray) | 1.8 | [Crystal](https://crystal-lang.org) |
|
||||
| [raylib-pas](https://github.com/tazdij/raylib-pas) | 3.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
|
||||
| [raylib-pascal](https://github.com/drezgames/raylib-pascal) | 2.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
|
||||
| [Graphics-Raylib](https://github.com/athreef/Graphics-Raylib) | 1.4 | [Perl](https://www.perl.org) |
|
||||
| [raylib-ruby](https://github.com/a0/raylib-ruby) | 2.6 | [Ruby](https://www.ruby-lang.org/en) |
|
||||
| [raylib-ruby-ffi](https://github.com/D3nX/raylib-ruby-ffi) | 2.0 | [Ruby](https://www.ruby-lang.org/en) |
|
||||
| [raylib-mruby](https://github.com/lihaochen910/raylib-mruby) | 2.5-dev | [mruby](https://github.com/mruby/mruby) |
|
||||
| [raylib-java](https://github.com/XoanaIO/raylib-java) | 2.0 | [Java](https://en.wikipedia.org/wiki/Java*(programming_language)) |
|
||||
| [clj-raylib](https://github.com/lsevero/clj-raylib) | 3.0 | [Clojure](https://clojure.org) |
|
||||
| [QuickJS-raylib](https://github.com/sntg-p/QuickJS-raylib) | 3.0 | [QuickJS](https://bellard.org/quickjs) |
|
||||
| [raylib-duktape](https://github.com/RobLoach/raylib-duktape) | 2.6 | [JavaScript (Duktape)](https://en.wikipedia.org/wiki/JavaScript) |
|
||||
| [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) | 2.6 | [ChaiScript](http://chaiscript.com) |
|
||||
| [raylib-squirrel](https://github.com/RobLoach/raylib-squirrel) | 2.5 | [Squirrel](http://www.squirrel-lang.org) |
|
||||
| [racket-raylib-2d](https://github.com/arvyy/racket-raylib-2d) | 2.5 | [Racket](https://racket-lang.org) |
|
||||
| [raylib-php-ffi](https://github.com/oraoto/raylib-php-ffi) | 2.4-dev | [PHP](https://en.wikipedia.org/wiki/PHP) |
|
||||
| [raylib-haxe](https://github.com/ibilon/raylib-haxe) | 2.4 | [Haxe](https://haxe.org) |
|
||||
| [ringraylib](https://github.com/ringpackages/ringraylib) | 2.6 | [Ring](http://ring-lang.sourceforge.net) |
|
||||
| [raylib-scm](https://github.com/yashrk/raylib-scm) | 2.5 | [Chicken Scheme](https://www.call-cc.org) |
|
||||
| [raylib-chibi](https://github.com/VincentToups/raylib-chibi) | 2.5 | [Chibi-Scheme](https://github.com/ashinn/chibi-scheme) |
|
||||
| [raylib-gambit-scheme](https://github.com/georgjz/raylib-gambit-scheme) | 3.1-dev | [Gambit Scheme](https://github.com/gambit/gambit) |
|
||||
| [Euraylib](https://github.com/gAndy50/Euraylib) | 3.0 | [Euphoria](https://openeuphoria.org) |
|
||||
| [raylib-odin](https://github.com/kevinw/raylib-odin) | 3.0 | [Odin](https://odin-lang.org) |
|
||||
| [vraylib](https://github.com/waotzi/vraylib) | 3.5 | [V](https://vlang.io) |
|
||||
| [raylib-vala](https://code.guddler.uk/mart/raylibVapi) | 3.0 | [Vala](https://wiki.gnome.org/Projects/Vala) |
|
||||
| [raylib-jai](https://github.com/kujukuju/raylib-jai) | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) |
|
||||
| [ray.zig](https://github.com/BitPuffin/zig-raylib-experiments) | 2.5 | [Zig](https://ziglang.org) |
|
||||
| [raylib-Ada](https://github.com/mimo/raylib-Ada) | 3.0 | [Ada](https://www.adacore.com/about-ada) |
|
||||
| [raykit](https://github.com/Gamerfiend/raykit) | **???** | [Kit](https://www.kitlang.org) |
|
||||
| [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) |
|
||||
| [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) |
|
||||
| [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) |
|
||||
| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) |
|
||||
| [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) |
|
||||
| [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) |
|
||||
| [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) |
|
||||
| [raylib-beef](https://github.com/M0n7y5/raylib-beef) | 3.0 | [Beef](https://www.beeflang.org) |
|
||||
| [raylib-never](https://github.com/never-lang/raylib-never) | 3.0 | [Never](https://github.com/never-lang/never) |
|
||||
| [raylib.cbl](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib) | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) |
|
||||
| Name | raylib Version | Language |
|
||||
| :--------------------------------------------------------------------------------------: | :--------------: | :---------------------------------------------------------------------: |
|
||||
| [raylib-cppsharp](https://github.com/phxvyper/raylib-cppsharp) | 2.5 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
|
||||
| [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) |
|
||||
| [RaylibFS](https://github.com/dallinbeutler/RaylibFS) | 2.5 | [F#](https://fsharp.org) |
|
||||
| [gforth-raylib](https://github.com/ArnautDaniel/gforth-raylib) | 3.5 | [Gforth](https://gforth.org) |
|
||||
| [raylib\*d](https://github.com/Sepheus/raylib_d) | 2.5 | [D](https://dlang.org) |
|
||||
| [bindbc-raylib](https://github.com/o3o/bindbc-raylib) | 3.0 | [D](https://dlang.org) |
|
||||
| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) |
|
||||
| [go-raylib](https://github.com/chunqian/go-raylib) | 3.5 | [Go](https://golang.org) |
|
||||
| [raylib-goplus](https://github.com/Lachee/raylib-goplus) | 2.6-dev | [Go](https://golang.org) |
|
||||
| [ray-go](https://github.com/hecate-tech/ray-go) | 2.6-dev | [Go](https://golang.org) |
|
||||
| [raylib-luamore](https://github.com/HDPLocust/raylib-luamore) | 3.0 | [Lua](http://www.lua.org) |
|
||||
| [LuaJIT-Raylib](https://github.com/Bambofy/LuaJIT-Raylib) | 2.6 | [Lua](http://www.lua.org) |
|
||||
| [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 2.5 | [Lua](http://www.lua.org) |
|
||||
| [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) | 2.0 | [Lua](http://www.lua.org) |
|
||||
| [raylib-lua](https://github.com/raysan5/raylib-lua) | 1.7 | [Lua](http://www.lua.org) |
|
||||
| [raylib-nelua](https://github.com/Andre-LA/raylib-nelua) | 3.0 | [Nelua](https://nelua.io) |
|
||||
| [raylib-nim](https://github.com/Skrylar/raylib-nim) | 2.0 | [Nim](https://nim-lang.org) |
|
||||
| [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) | 1.7 | [Nim](https://nim-lang.org) |
|
||||
| [nim-raylib](https://github.com/tomc1998/nim-raylib) | 3.1-dev | [Nim](https://nim-lang.org) |
|
||||
| [raylib-Forever](https://github.com/Guevara-chan/Raylib-Forever) | auto | [Nim](https://nim-lang.org) |
|
||||
| [NimraylibNow!](https://github.com/greenfork/nimraylib_now) | 4.2 | [Nim](https://nim-lang.org) |
|
||||
| [naylib](https://github.com/planetis-m/naylib) | **5.6-dev** | [Nim](https://nim-lang.org) |
|
||||
| [raylib-haskell](https://github.com/DevJac/raylib-haskell) | 2.0 | [Haskell](https://www.haskell.org) |
|
||||
| [hb-raylib](https://github.com/MarcosLeonardoMendezGerencir/hb-raylib) | 3.7 | [Harbour](https://harbour.github.io) |
|
||||
| [raylib-cr](https://github.com/AregevDev/raylib-cr) | 2.5-dev | [Crystal](https://crystal-lang.org) |
|
||||
| [raylib.cr](https://github.com/sam0x17/raylib.cr) | 2.0 | [Crystal](https://crystal-lang.org) |
|
||||
| [cray](https://gitlab.com/Zatherz/cray) | 1.8 | [Crystal](https://crystal-lang.org) |
|
||||
| [raylib-pas](https://github.com/tazdij/raylib-pas) | 3.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
|
||||
| [raylib-pascal](https://github.com/drezgames/raylib-pascal) | 2.0 | [Pascal](https://en.wikipedia.org/wiki/Pascal*(programming*language)) |
|
||||
| [Graphics-Raylib](https://github.com/athreef/Graphics-Raylib) | 1.4 | [Perl](https://www.perl.org) |
|
||||
| [Relib](https://github.com/RedCubeDev-ByteSpace/Relib) | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) |
|
||||
| [raylib-ruby](https://github.com/a0/raylib-ruby) | 2.6 | [Ruby](https://www.ruby-lang.org/en) |
|
||||
| [raylib-ruby-ffi](https://github.com/D3nX/raylib-ruby-ffi) | 2.0 | [Ruby](https://www.ruby-lang.org/en) |
|
||||
| [raylib-mruby](https://github.com/lihaochen910/raylib-mruby) | 2.5-dev | [mruby](https://github.com/mruby/mruby) |
|
||||
| [raylib-java](https://github.com/XoanaIO/raylib-java) | 2.0 | [Java](https://en.wikipedia.org/wiki/Java*(programming_language)) |
|
||||
| [kaylib](https://github.com/electronstudio/kaylib) | 3.7 | [Kotlin/native](https://kotlinlang.org) |
|
||||
| [clj-raylib](https://github.com/lsevero/clj-raylib) | 3.0 | [Clojure](https://clojure.org) |
|
||||
| [QuickJS-raylib](https://github.com/sntg-p/QuickJS-raylib) | 3.0 | [QuickJS](https://bellard.org/quickjs) |
|
||||
| [raylib-duktape](https://github.com/RobLoach/raylib-duktape) | 2.6 | [JavaScript (Duktape)](https://en.wikipedia.org/wiki/JavaScript) |
|
||||
| [rayjule](https://github.com/SabeDoesThings/rayjule) | **5.5** | [Jule](https://jule.dev/) |
|
||||
| [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) | 2.6 | [ChaiScript](http://chaiscript.com) |
|
||||
| [raylib-squirrel](https://github.com/RobLoach/raylib-squirrel) | 2.5 | [Squirrel](http://www.squirrel-lang.org) |
|
||||
| [racket-raylib-2d](https://github.com/arvyy/racket-raylib-2d) | 2.5 | [Racket](https://racket-lang.org) |
|
||||
| [raylib-php-ffi](https://github.com/oraoto/raylib-php-ffi) | 2.4-dev | [PHP](https://en.wikipedia.org/wiki/PHP) |
|
||||
| [raylib-phpcpp](https://github.com/oraoto/raylib-phpcpp) | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) |
|
||||
| [raylib-haxe](https://github.com/ibilon/raylib-haxe) | 2.4 | [Haxe](https://haxe.org) |
|
||||
| [ringraylib](https://github.com/ringpackages/ringraylib) | 2.6 | [Ring](http://ring-lang.sourceforge.net) |
|
||||
| [raylib-scm](https://github.com/yashrk/raylib-scm) | 2.5 | [Chicken Scheme](https://www.call-cc.org) |
|
||||
| [raylib-chibi](https://github.com/VincentToups/raylib-chibi) | 2.5 | [Chibi-Scheme](https://github.com/ashinn/chibi-scheme) |
|
||||
| [raylib-gambit-scheme](https://github.com/georgjz/raylib-gambit-scheme) | 3.1-dev | [Gambit Scheme](https://github.com/gambit/gambit) |
|
||||
| [Euraylib](https://github.com/gAndy50/Euraylib) | 3.0 | [Euphoria](https://openeuphoria.org) |
|
||||
| [raylib-odin](https://github.com/kevinw/raylib-odin) | 3.0 | [Odin](https://odin-lang.org) |
|
||||
| [vraylib](https://github.com/waotzi/vraylib) | 3.5 | [V](https://vlang.io) |
|
||||
| [raylib-vala](https://code.guddler.uk/mart/raylibVapi) | 3.0 | [Vala](https://wiki.gnome.org/Projects/Vala) |
|
||||
| [raylib-jai](https://github.com/kujukuju/raylib-jai) | 3.1-dev | [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md) |
|
||||
| [ray.zig](https://github.com/BitPuffin/zig-raylib-experiments) | 2.5 | [Zig](https://ziglang.org) |
|
||||
| [raylib-Ada](https://github.com/mimo/raylib-Ada) | 3.0 | [Ada](https://www.adacore.com/about-ada) |
|
||||
| [raykit](https://github.com/Gamerfiend/raykit) | **???** | [Kit](https://www.kitlang.org) |
|
||||
| [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) |
|
||||
| [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) |
|
||||
| [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) |
|
||||
| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) |
|
||||
| [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) |
|
||||
| [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) |
|
||||
| [pyraylib](https://github.com/Ho011/pyraylib) | 3.7 | [Python](https://www.python.org) |
|
||||
| [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) |
|
||||
| [raylib-beef](https://github.com/M0n7y5/raylib-beef) | 3.0 | [Beef](https://www.beeflang.org) |
|
||||
| [raylib-never](https://github.com/never-lang/raylib-never) | 3.0 | [Never](https://github.com/never-lang/never) |
|
||||
| [raylib.cbl](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib) | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) |
|
||||
|
||||
|
||||
Missing some language or wrapper? Feel free to create a new one! :)
|
||||
|
||||
|
||||
252
CHANGELOG
@ -3,6 +3,258 @@ changelog
|
||||
|
||||
Current Release: raylib 6.0 (23 April 2026)
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
Release: raylib 6.2 (xx Sep 2026)
|
||||
-------------------------------------------------------------------------
|
||||
KEY CHANGES:
|
||||
- REDESIGNED: Image API for more alignment with Texture API
|
||||
- REDESIGNED: File API for more standard return result values
|
||||
- REVIEWED: Shapes lines drawing functions, added new ones and unify behaviour
|
||||
|
||||
Detailed changes (until 12-Sept-2026):
|
||||
|
||||
[rcore] ADDED: `IsPathDirectory()`, for convenience and more readability at user code by @raysan5
|
||||
[rcore] ADDED: `IsPathAbsolute()`, check absolute paths by @raysan5
|
||||
[rcore] ADDED: `IsFileHidden()`, check file hidden (OS-dependant) by @raysan5
|
||||
[rcore] REVIEWED: `File*()` functions for consistent return result value by @raysan5 -WARNING-
|
||||
[rcore] REVIEWED: Not updating mouse.previousPosition when `SetMousePosition()` #5962 by @raysan5 -WARNING-
|
||||
[rcore] REVIEWED: Use `rlgl` provided interface instead of `rlsw` direct access by @raysan5
|
||||
[rcore] REVIEWED: Set mouse position to (0,0) when mouse leaves window area #5945 by @raysan5
|
||||
[rcore] REVIEWED: Multiple string boundary handling (#5812) by @zhaob1n
|
||||
[rcore] REVIEWED: Gamepad lower-bound guard to six sibling functions (#5938) by @mahirhir
|
||||
[rcore] REVIEWED: Fix logging format for automation event capacity warning (#5986) by @GideonSerf
|
||||
[rcore] REVIEWED: Fix initial macOS window size (#5967) by @loukamb
|
||||
[rcore] REVIEWED: Fix clipboard image memory leak (#5968) by @LuisR385
|
||||
[rcore] REVIEWED: `TakeScreenshot()`, support absolute paths by @raysan5
|
||||
[rcore] REVIEWED: `OpenURL()`, added some safety checks to mitigate malicious url inputs - ROS: `CLN-002` by @raysan5 -WARNING-
|
||||
[rcore] REVIEWED: `LoadAutomationEventList()` - ROS: `CLN-005`, `CLN-006` by @raysan5
|
||||
[rcore] REVIEWED: `GetWindowHandle()`, to be consistent between backends, fix #5885 by @raysan5
|
||||
[rcore] REVIEWED: `GetWindowPosition()` #5932 by @raysan5
|
||||
[rcore] REVIEWED: `GetTime()`, small addition for RPI Pico 2 by @raysan5
|
||||
[rcore] REVIEWED: `GetCurrentMonitor()`, fix for integer overflow in distance calculation (#5842) by @Vasilis-Narain
|
||||
[rcore] REVIEWED: `FileMove()`, additional security checks by @raysan5
|
||||
[rcore] REVIEWED: `FileCopy()`, create directory to copy if it does not exist (#5920) by @InviseDivine
|
||||
[rcore] REVIEWED: `FileMove()`, fix deleting files if `FileCopy()` fails (#5806) by @Lucrecious -WARNING-
|
||||
[rcore] REVIEWED: `IsPathAbsolute()`, remove `isalpha()` dependency by @raysan5
|
||||
[rcore] REVIEWED: `ComputeSHA1()`, fix undefined behaviour (#5957) by @TheFissk
|
||||
[rcore] REVIEWED: `ComputeSHA256()`, wrong hash when message length mod 64 is 56..59 (#6144) by @killerdevildog -WARNING-
|
||||
[rcore] REVIEWED: `GetPrevDirectoryPath()` behavior to better support side cases (#6073) by @luphi
|
||||
[rcore] REVIEWED: `GetGamepadAxisCount()`, `GetGamepadName()`, bounds-check gamepad index (#5937) by @szarta
|
||||
[rcore][GLFW] REVIEWED: `GetClipboardImage()`, fix creating new connection under X11 (#5871) by @steampuker
|
||||
[rcore][GLFW] REVIEWED: Borderless-windowed mode being always on top (#5868) by @auwsmit
|
||||
[rcore][GLFW] REVIEWED: Clipboard image memory leak (GLFW, RGFW) (#6103) by @omaribrahimsaad
|
||||
[rcore][GLFW] REVIEWED: Do not reset mouse position user when user is off window (#6134) by @jestarray
|
||||
[rcore][GLFW] REVIEWED: `Font` symbol conflict (#6094) by @M374LX
|
||||
[rcore][RGFW] REVIEWED: Add fullscreen behaviour on size 0 window creation (#5859) by @keks137
|
||||
[rcore][RGFW] REVIEWED: Fix window Y position reading X in RGFW move callback (#6044) by @latent-9
|
||||
[rcore][SDL] REVIEWED: Use precise mouse wheel values (#5830) by @Menduist
|
||||
[rcore][SDL] REVIEWED: Fix SDL3 wrong joystick functions usage (#5948) by @0xFishbyte
|
||||
[rcore][DRM] REVIEWED: Silence warnings when using GRAPHICS_API_OPENGL_SOFTWARE (#5839) by @NighthowlerStudios
|
||||
[rcore][DRM] REVIEWED: Segfault on some NVIDIA proprietary drivers (#5960) by @girvel
|
||||
[rcore][DRM] REVIEWED: Raise MAX_DRM_CACHED_BUFFERS to 4 and warn when the cache fills (#6107) by @jtakakura
|
||||
[rcore][Web] REVIEWED: Fix for stale mouse position (#5981) by @largenumberhere
|
||||
[rcore][Win32] ADDED: GetClipboardImage() (#6091) by @omaribrahimsaad
|
||||
[rcore][Win32] REVIEWED: Use `CORE.Input.Keyboard.exitKey` when handling window closing (#5911) by @aceinetx
|
||||
[rcore][Win32] REVIEWED: Security fixes (#5899) by @M374LX
|
||||
[rcore][Win32] REVIEWED: Handle conflict with `PlaySoundW()` for wide string builds (#6140) by @JeffM2501
|
||||
[rcore][Android] REVIEWED: Restore face-button input on Android gamepads (#5824) by @Tubbles
|
||||
[rcore][Android] REVIEWED: Relaunch hang after destroy while paused (#6040) by @get-charlie
|
||||
[rcore][Emscripten] REVIEWED: GetTime(), fix time calculation (#6061) by @andzdroid
|
||||
[rcore][Emscripten] REVIEWED: Handle emscripten keyboard events (#6067) by @andzdroid
|
||||
[rcore][Emscripten] REVIEWED: Invert emscripten scroll wheel direction (#6104) by @andzdroid
|
||||
[rcore][Emscripten] REVIEWED: Update emscripten mouse handling (#6070) by @andzdroid
|
||||
[rlsw] ADDED: Double buffering support and compiler requirements Pico 2 (#5994) by @NighthowlerStudios
|
||||
[rlsw] ADDED: `GL_SHADING_LANGUAGE_VERSION` for `swGetString()` by @raysan5
|
||||
[rlsw] REVIEWED: Variant dispatch refactor and render optimizations (#5996) by @Bigfoot71
|
||||
[rlgl] REVIEWED: `rlGetPixelDataSize()`, fix pixel data size regressions (#5984) by @GideonSerf
|
||||
[rlgl] REVIEWED: `rlPushMatrix()`, fix matrix stack overflow (#5935) by @szarta
|
||||
[rlgl] REVIEWED: `rlLoadTexture()`, add power-of-two check for GL_REPEAT wrap mode (#5820) by @noinodev
|
||||
[rlgl] REVIEWED: Shader attribute/uniform default names can not be overriden #5925 by @raysan5
|
||||
[rlgl] REVIEWED: Fix DRM/EGL segfault on some NVIDIA proprietary drivers (#5960) by @girvel
|
||||
[rlgl] REVIEWED: Use `rlGetPixelDataSize()` instead of `GetPixelDataSize()` (#6024) by @leoagomes
|
||||
[rlgl] REVIEWED: `rlGetActiveFramebuffer()` supported on OpenGL ES 2.0 (#6115) by @JoeStrout
|
||||
[rlsw] REVIEWED: Replace `SW_TEXTURE_REPEAT_POT_FAST` with `SW_SUPPORT_NPOT_TEXTURE` (#5901) by @Bigfoot71
|
||||
[rlsw] REVIEWED: Fix triangle and quad spans applying pixels out of bounds (#5849) by @NighthowlerStudios
|
||||
[rlsw] REVIEWED: Fix swScissor() Y-axis clipping inversion in software renderer (#5976) by @thiagomucci
|
||||
[rlsw] REVIEWED: Fix persistent alpha blending state (#5964) by @iztanos
|
||||
[rlsw] REVIEWED: ESP32 optimizations (#5827) by @jensroth-git
|
||||
[rlsw] REVIEWED: Internal functions declarations (#6028) by @Bigfoot71
|
||||
[rlsw] REVIEWED: Optimizations for embedded and compiler requirements Pico 2 (#5994) by @NighthowlerStudios
|
||||
[rlsw] REVIEWED: Rename public compile-time option prefix to `RLSW_` (#6029) by @Bigfoot71
|
||||
[rlsw] REVIEWED: Variant dispatch refactor and other improvements (#5996) by @Bigfoot71
|
||||
[rshapes] ADDED: `Draw*LinesEx()` functions (#6072) by @MatthewRoush
|
||||
[rshapes] RENAMED: `GetSplinePointBezierQuad()` to `GetSplinePointBezierQuadratic()` by @raysan5 -WARNING-
|
||||
[rshapes] REVIEWED: Reorder drawing functions by number of vertices by @raysan5
|
||||
[rshapes] REVIEWED: Comments to be more descriptive by @raysan5
|
||||
[rshapes] REVIEWED: `DrawRectangleRoundedLinesEx()`, not scaling with transform when thick=1 (#5980) by @SamaelHeaven
|
||||
[rshapes] REVIEWED: `DrawRectangleRoundedLines()` (#5992) by @MatthewRoush
|
||||
[rshapes] REVIEWED: `DrawRectangleRounded()`, automatic segments count (#5875) by @anstropleuton
|
||||
[rshapes] REVIEWED: `DrawRectangleRounded()`, `DrawRectangleRoundedLinesEx()`, fix auto segment rounded-corner math (#5883) by @ghera
|
||||
[rshapes] REVIEWED: `CheckCollisionLines()`, add NULL check (#5802) by @bielern
|
||||
[rshapes] REVIEWED: `Draw*LinesEx()`, inconsistencies handling of `thick` parameter (#6035) by @MatthewRoush
|
||||
[rshapes] REVIEWED: `DrawCircleSector()` (#6045) by @MatthewRoush
|
||||
[rshapes] REVIEWED: `DrawPolyLinesEx()` (#6004) by @MatthewRoush
|
||||
[rshapes] REVIEWED: `DrawPolyLinesEx()` line thickness (#6014) by @MatthewRoush
|
||||
[rshapes] REVIEWED: `DrawRectangleLinesEx()` (#6027) by @MatthewRoush
|
||||
[rshapes] REVIEWED: `DrawRectangleRoundedLines()` (#5992) by @MatthewRoush
|
||||
[rtextures] ADDED: `LoadRenderTextureEx()` with user defined pixel format (#6114) by @JeffM2501
|
||||
[rtextures] ADDED: `ImageDrawLineStrip()` by @raysan5
|
||||
[rtextures] ADDED: `DrawTriangleGradient()` by @raysan5
|
||||
[rtextures] ADDED: `DrawCircleLinesEx()`, simpler naming than `DrawRing()` by @raysan5
|
||||
[rtextures] ADDED: `ImageDrawCircleGradient()` by @raysan5
|
||||
[rtextures] ADDED: Support for .pep image fileformat, useful for pixel-art by @raysan5
|
||||
[rtextures] RENAMED: `ImageDrawTriangleEx()` to `ImageDrawTriangleGradient()` by @raysan5 -WARNING-
|
||||
[rtextures] REDESIGNED: `ImageDraw()`, align with `DrawTexture()` by @raysan5 -WARNING-
|
||||
[rtextures] REDESIGNED: `ImageDrawRectangleLines()`, consistency with `DrawRectangleLines()` by @raysan5 -WARNING-
|
||||
[rtextures] REVIEWED: `DrawRectangleLinesEx()`, avoid early-return by @raysan5
|
||||
[rtextures] REVIEWED: `GetPixelColor()` reading the wrong bits for R5G5B5A1 blue (#6113) by @dylanpulver
|
||||
[rtextures] REVIEWED: `ImageDrawCircle()`, asymmetry compared with `DrawCircle()` (#6118) by @Risu-swift
|
||||
[rtextures] REVIEWED: `LoadImageFromTexture()` for wasm by @raysan5
|
||||
[rtextures] REVIEWED: `ImageFromImage()` - ROS: `CLN-007` by @raysan5
|
||||
[rtextures] REVIEWED: `ImageFromImage()`, rectangle validation using strict comparisons (#5979) by @CommandPrompt-Wang
|
||||
[rtextures] REVIEWED: `ImageFromImage()` heap-buffer-overflow on compressed formats (#5991) by @gummyniki
|
||||
[rtextures] REVIEWED: `ImageToImage()`, reorganize conditionals checks optimization by @raysan5
|
||||
[rtextures] REVIEWED: `ImageDrawLine()`, rounding and length fix (#5896) by @Kaggen67
|
||||
[rtextures] REVIEWED: `ImageColorContrast()` parameter type, consistent with other `Image*()` functions by @raysan5 -WARNING-
|
||||
[rtextures] REVIEWED: `GetPixelDataSize()`, avoid allocations >2GB - ROS: `CLN-013` by @raysan5
|
||||
[rtextures] REVIEWED: `GetPixelColor()` const by @raysan5
|
||||
[rtext] REVIEWED: `LoadFontEx()`, `LoadFontFromMemory()`, additional warnings (#5864) by @CrackedPixel
|
||||
[rtext] REVIEWED: `TextToSnake()`, not considering spaces properly by @raysan5
|
||||
[rtext] REVIEWED: `TextSubtext()`, fix returning empty string when position is 0 (#5975) by @thiagomucci
|
||||
[rtext] REVIEWED: `TextReplaceBetween()`, fix buffer overflow (#5936) by @szarta
|
||||
[rtext] REVIEWED: `TextInsertAlloc()`, overflow by correcting loop bounds (#5982) by @GideonSerf
|
||||
[rtext] REVIEWED: `TextJoin()`, `TextSubtext()`, `TextInsert*()` - ROS: `CLN-018` by @raysan5
|
||||
[rtext] REVIEWED: `LoadFontFromImage()`, memory leak (#6100) by @ApexNadir
|
||||
[rtext] REVIEWED: `TextInsert()`/`TextInsertAlloc()` (#6021) by @SewerynKaminski
|
||||
[rtext] REVIEWED: `TextSplit()` reading past its buffer on text of 1024 bytes (#6136) by @MaxFreedomPollard
|
||||
[rtext] REVIEWED: `TextToPascal()`/`TextToCamel()` truncating text after a separator (#6132) by @MaxFreedomPollard
|
||||
[rmodels] REDESIGNED: `DrawCapsule()`, `DrawCapsuleWires()`, parameter order by @raysan5 -WARNING-
|
||||
[rmodels] REVIEWED: Fix glTF skinning when joints have non-joint parent nodes (#5876) by @cseelhoff
|
||||
[rmodels] REVIEWED: Change `boneCount` field type to `unsigned int` (#5955) by @lauchimoon
|
||||
[rmodels] REVIEWED: `LoadGLTF()`, use inverse bind matrices for bind pose (#5832) by @fyl2xp1
|
||||
[rmodels] REVIEWED: `IsModelValid()` #5780 by @raysan5
|
||||
[rmodels] REVIEWED: `GenMeshTorus()`, improved comments (#5934) by @EugenioBarbieriViale
|
||||
[rmodels] REVIEWED: `DrawSphereWires()`, code optimization (#6000) by @oscujic
|
||||
[rmodels] REVIEWED: `DrawSphereWires()`, code optimization (#6000) by @oscujic
|
||||
[rmodels] REVIEWED: `DrawCapsule()`, `DrawCapsuleWires()`, validate minimum rings (#5909) by @LuisR385
|
||||
[rmodels] REVIEWED: `UnloadModel()`, fix memory leak (#5907) by @LuisR385
|
||||
[rmodels] REVIEWED: GLTF animation interpolation (#6007) by @lassade
|
||||
[rmodels] REVIEWED: glTF pose sampled at the end of an animation returning a pose from the start (#6048) by @LeFede
|
||||
[raudio] REVIEWED: `UpdateSound()`, missleading parameter name by @raysan5
|
||||
[raudio] REVIEWED: `UnloadSoundAlias()`, prevent leak (#5857) by @Peter0x44
|
||||
[raudio] REVIEWED: Remove extra `drflac_free()` call (#5916) by @CrackedPixel
|
||||
[raudio] REVIEWED: Fix memory leak when loading .wav files (#5963) by @LuisR385
|
||||
[raudio] REVIEWED: Define missing `UnloadFileData()` on standalone mode (#5787) by @rigidatoms
|
||||
[raudio] REVIEWED: Update to latest DR libs to fix some warnings in MSVC (#5808) by @JeffM2501
|
||||
[raudio] REVIEWED: `CloseAudioDevice()`, crash when uninit device before mutex (#6039) by @get-charlie
|
||||
[raymath] ADDED: Operator overload for (float * Vector) (#5815) by @alphahex99
|
||||
[raymath] REVIEWED: `MatrixCompose()` to follow raymath conventions (#6133) by @carlost0
|
||||
|
||||
[build] REMOVED: Unmaintained project: 4coder by @raysan5
|
||||
[build] REMOVED: Unmaintained project: VS2019-Android by @raysan5
|
||||
[build][Make] REVIEWED: Add `ANDROID_ARCH` check (#5888) by @Fipaan
|
||||
[build][Make] REVIEWED: Re-enable `GLFW_LINUX_ENABLE_WAYLAND` flag by default #5816 by @raysan5
|
||||
[build][Make] REVIEWED: examples/Makefile after testing on OSX (#6077) by @WilliamIsMe1
|
||||
[build][Make] REVIEWED: Detect the recipe shell for proper clean (#6146) by @Peter0x44
|
||||
[build][VS2022] REVIEWED: x64 build compatibility support (#6052) (#6053) by @yoobezxc
|
||||
[build][CMake] ADDED: Support for Win32 platform + examples (#5855) by @CrackedPixel
|
||||
[build][CMake] REVIEWED: Fix config.h parsing into cmake options (#5844) by @Peter0x44
|
||||
[build][CMake] REVIEWED: Add configure-time test for libatomic requirement (#5847) by @Peter0x44
|
||||
[build][CMake] REVIEWED: Remove `raudio` and `rmodels` modules if disabled (#5878) by @NighthowlerStudios
|
||||
[build][CMake] REVIEWED: Remove GLFW_BUILD warnings for platform SDL (#5865) by @jestarray
|
||||
[build][CMake] REVIEWED: Reduce minimum CMake version from 3.25 to 3.22 (#5890) by @RobLoach
|
||||
[build][CMake] REVIEWED: Fix static link dependencies (#5990) by @meta-legend
|
||||
[build][CMake] REVIEWED: Fix standalone configuration of examples project (#6079) by @zaveshaa
|
||||
[build][CMake] REVIEWED: Propagate Cocoa backend frameworks to consumers of static raylib on macOS (#6086) by @zaveshaa
|
||||
[build][Zig] REVIEWED: Support wasm examples building (#5811) by @shadeops
|
||||
[build][Zig] REVIEWED: Avoid building examples all the time (#5869) by @jn-jairo
|
||||
[build][Zig] REVIEWED: Avoid building web examples all the time (#6006) by @jn-jairo
|
||||
[build][Zig] REVIEWED: Update to raygui 5.0 (#6005) by @jn-jairo
|
||||
[build][CI] REVIEWED: GitHub Actions update to latest actions versions by @raysan5
|
||||
[build][CI] REVIEWED: `build_examples_windows.yml`, use latest actions versions by @raysan5
|
||||
[build][CI] REVIEWED: `analyze_codeql.yml`, use latest actions versions by @raysan5
|
||||
[build][CI] REVIEWED: `setup-emsdk`, use latest actions version by @raysan5
|
||||
|
||||
[bindings] ADDED: Recomendations for binding authors (#6141) by @JeffM2501
|
||||
[bindings] ADDED: sola-raylib (6.0) (#5790, #5795) by @brettchalupa
|
||||
[bindings] ADDED: gclang-raylib (6.0) (#5850) by @gnuchanos
|
||||
[bindings] ADDED: mach-raylib (#6059) by @Angluca
|
||||
[bindings] ADDED: solod (#6102) by @nalgeon
|
||||
[bindings] ADDED: raymojo (#6076) by @RobertFlexx
|
||||
[bindings] ADDED: raylib_mojo, for Mojo language (#6093) by @willGuimont
|
||||
[bindings] ADDED: rayscal, for Scala Native (#6019) by @RobertFlexx
|
||||
[bindings] ADDED: raylib-elfscript, for ElfScript (#6036) by @ohmtal
|
||||
[bindings] ADDED: raylib component pascal/oberon2 bindings (#6055) by @RobertFlexx
|
||||
[bindings] ADDED: raylib binding for modula 2 and 3 (#6068) by @RobertFlexx
|
||||
[bindings] ADDED: raystar (#6075) by @RobertFlexx
|
||||
[bindings] UPDATED: vala-vapi to raylib 6.0 (#5789) by @edwood-grant
|
||||
[bindings] UPDATED: raylib_dart to raylib 6.0 (#5917) by @dzylikecode
|
||||
[bindings] UPDATED: raylib4fb to raylib 6.0 (#5813) by @mudhairless
|
||||
[bindings] UPDATED: raylib-d to raylib 6.0 (#5799) by @schveiguy
|
||||
[bindings] UPDATED: raylib-cpp to raylib 6.0 (#5785) by @RobLoach
|
||||
[bindings] UPDATED: raylib-go to raylib 6.0 (#5866) by @JupiterRider
|
||||
[bindings] UPDATED: raylib-cpp to raylib 6.0 (#5785) by @RobLoach
|
||||
[bindings] UPDATED: raylib-zig to raylib 6.0 (#5886) by @coal-rock
|
||||
[bindings] UPDATED: Deno-Raylib to raylib 6.0 (#5821) by @JJLDonley
|
||||
[bindings] UPDATED: raylib-cs to raylib 6.0 (#5887) by @rgebee
|
||||
[bindings] UPDATED: ReiLua to raylib 6.0 (#5959) by @nullstare
|
||||
[bindings] UPDATED: Raylib-lua to raylib 5.5 (#5884) by @keyle
|
||||
[bindings] UPDATED: Ray4Laz to raylib 6.0 (#5784) by @GuvaCode
|
||||
[bindings] UPDATED: EuRaylib to raylib 6.0 (#6034) by @gAndy50
|
||||
[bindings] UPDATED: raylib-ocaml to raylib 6.0 (#5912) by @tjammer
|
||||
[bindings] UPDATED: raylib-jai to raylib 6.0 (#5928) by @ahmedqarmout2
|
||||
[bindings] UPDATED: raylib-c3 to raylib 6.0 (#5819) by @surrealism21
|
||||
[bindings] UPDATED: raylib-asm to raylib 6.0 (#6033) by @gAndy50
|
||||
[bindings] UPDATED: fortran-raylib to raylib 6.0 (#6060) by @interkosmos
|
||||
[bindings] UPDATED: raylib-py to raylib 6.0 (#6095) by @overdev
|
||||
[bindings] UPDATED: h-raylib to raylib 6.0 (#6142) by @Anut-py
|
||||
|
||||
[examples] ADDED: `core_scissor_shape` (#6032) by @davidbuzatto
|
||||
[examples] ADDED: `models_mesh_uv_painting` (#6084) by @PanicTitan
|
||||
[examples] ADDED: `models_procedural_decals` (#6083) by @PanicTitan
|
||||
[examples] ADDED: `shaders_lights_bloom` (#6081) by @PanicTitan
|
||||
[examples] ADDED: `shapes_outlines_testbed` (#6072) by @MatthewRoush
|
||||
[examples] ADDED: `shapes_outlines_thickness` (#6037) by @MatthewRoush
|
||||
[examples] ADDED: `shapes_polygon_lines` (#6023) by @MatthewRoush
|
||||
[examples] ADDED: `textures_portal_window` (#6082) by @PanicTitan
|
||||
[examples] REVIEWED: `shaders_shadowmap_rendering` by @raysan5
|
||||
[examples] REVIEWED: `models_mesh_uv_painting` by @raysan5
|
||||
[examples] REVIEWED: `shaders_lights_bloom` by @raysan5
|
||||
[examples] REVIEWED: `textures_portal_window` by @raysan5
|
||||
[examples] REVIEWED: `core_smooth_pixelperfect` (#5803) by @rose-mtz
|
||||
[examples] REVIEWED: `core_directory_files` (#5823) by @MAXDVVV
|
||||
[examples] REVIEWED: `shapes_ball_physics`, move window for ball shake (#5791) by @Sebbl0508
|
||||
[examples] REVIEWED: `textures_image_drawing` by @raysan5
|
||||
[examples] REVIEWED: `models_basic_voxel` by @raysan5
|
||||
[examples] REVIEWED: `models_animation_blending` by @raysan5
|
||||
[examples] REVIEWED: `shaders_*`, `pbr.fs`, using wrong uniform value (#5965) by @raysan5
|
||||
|
||||
[rlparser] ADDED: S-Expression output type (#5943) by @VisenDev
|
||||
[rlparser] REVIEWED: Path fixes (#5794) by @gigamonster256
|
||||
[rlparser] REVIEWED: Fix formatting to follow raylib conventions (#6127) by @Nomobyte
|
||||
[rlparser] REVIEWED: Fix type aliases, added support to type pointers (#6126) by @Nomobyte
|
||||
[rexm] ADDED: New command: clean (#6124) by @MatthewRoush
|
||||
[rexm] REVIEWED: Crash when adding a new textures or audio examples (#6089) by @PanicTitan
|
||||
[rexm] REVIEWED: Leave environment setup up to the user (#6101) by @MatthewRoush
|
||||
[rexm] REVIEWED: Makefile and change web local testing port number (#6123) by @MatthewRoush
|
||||
[rexm] REVIEWED: Simplify code, latest w64devkit supports `make` directly, no need for `mingw32-make` by @raysan5
|
||||
[misc] ADDED: SECURITY.md document by @raysan5
|
||||
[misc] REVIEWED: Several functions `const` correctness by @raysan5
|
||||
[misc] REVIEWED: `strncpy()` replaced by `snprintf()` for safety by @raysan5
|
||||
[misc] REVIEWED: Minimize `long long` usage in all raylib by @raysan5
|
||||
[misc] REVIEWED: Comments for consistency and spelling by @raysan5
|
||||
[misc] REVIEWED: Some Rectangle parameters with more descriptive names by @raysan5
|
||||
[misc] REVIEWED: Shift `__cplusplus` check to a higher level for `bool` type define (#5804) by @lamweilun
|
||||
[external] ADDED: `rprand_get_value_raw()` to `rprand` library by @raysan5
|
||||
[external] UPDATED: GLFW to 3.5.1 (#6051) by @M374LX
|
||||
[external] UPDATED: miniaudio to 0.11.25 (#6050) by @M374LX
|
||||
[external] UPDATED: `raygui` to latest master (raygui 5.0) by @raysan5
|
||||
[external] REVIEWED: `jar_mod_load_file()`, check fread return value (#5840) by @fffaraz
|
||||
[external] REVIEWED: `tiny_obj_loader` Replace `assert()` by runtime checks - ROS: `CLN-012` by @raysan5
|
||||
[external] REVIEWED: `fix_win32_compatibility.h`, fix for newer windows SDK versions (#6088) by @JeffM2501
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
Release: raylib 6.0 (23 April 2026)
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
#this change avoid the warning that appear when we include raylib using Cmake fatch content
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
project(raylib)
|
||||
|
||||
# Avoid excessive expansion of variables in conditionals. In particular, if
|
||||
@ -29,7 +28,7 @@ include(CompilerFlags)
|
||||
# Registers build options that are exposed to cmake
|
||||
include(CMakeOptions.txt)
|
||||
|
||||
if (UNIX AND NOT APPLE AND NOT "${PLATFORM}" MATCHES "DRM" AND NOT "${PLATFORM}" MATCHES "Web")
|
||||
if (UNIX AND NOT APPLE AND NOT "${PLATFORM}" MATCHES "DRM" AND NOT "${PLATFORM}" MATCHES "Web" AND NOT "${PLATFORM}" MATCHES "SDL")
|
||||
if (NOT GLFW_BUILD_WAYLAND AND NOT GLFW_BUILD_X11)
|
||||
message(FATAL_ERROR "Cannot disable both Wayland and X11")
|
||||
endif()
|
||||
|
||||
@ -6,7 +6,7 @@ if(EMSCRIPTEN)
|
||||
# When configuring web builds with "emcmake cmake -B build -S .", set PLATFORM to Web by default
|
||||
SET(PLATFORM Web CACHE STRING "Platform to build for.")
|
||||
endif()
|
||||
enum_option(PLATFORM "Desktop;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.")
|
||||
enum_option(PLATFORM "Desktop;Win32;Web;WebRGFW;Android;Raspberry Pi;DRM;SDL;RGFW;Memory" "Platform to build for.")
|
||||
|
||||
enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?")
|
||||
|
||||
@ -29,11 +29,15 @@ option(GLFW_BUILD_WAYLAND "Build the bundled GLFW with Wayland support" OFF)
|
||||
option(GLFW_BUILD_X11 "Build the bundled GLFW with X11 support" ON)
|
||||
|
||||
option(INCLUDE_EVERYTHING "Include everything disabled by default (for CI usage)" OFF)
|
||||
set(OFF ${INCLUDE_EVERYTHING} CACHE INTERNAL "Replace any OFF by default with \${OFF} to have it covered by this option")
|
||||
|
||||
include(ParseConfigHeader)
|
||||
|
||||
foreach(FLAG IN LISTS CONFIG_HEADER_FLAGS)
|
||||
string(REGEX MATCH "([^=]+)=(.+)" _ ${FLAG})
|
||||
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CMAKE_MATCH_2} CUSTOMIZE_BUILD ${CMAKE_MATCH_2})
|
||||
set(CONFIG_HEADER_FLAG_DEFAULT ${CMAKE_MATCH_2})
|
||||
if (INCLUDE_EVERYTHING AND "${CONFIG_HEADER_FLAG_DEFAULT}" STREQUAL "OFF")
|
||||
set(CONFIG_HEADER_FLAG_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
cmake_dependent_option(${CMAKE_MATCH_1} "" ${CONFIG_HEADER_FLAG_DEFAULT} CUSTOMIZE_BUILD ${CONFIG_HEADER_FLAG_DEFAULT})
|
||||
endforeach()
|
||||
|
||||
@ -25,7 +25,7 @@ Functions params | lowerCase | `width`, `height`
|
||||
Ternary Operator | (condition)? result1 : result2 | `printf("Value is 0: %s", (value == 0)? "yes" : "no");`
|
||||
|
||||
Some other conventions to follow:
|
||||
- **ALWAYS** initialize all defined variables.
|
||||
- **ALWAYS** initialize all defined variables, avoid defining variables in same code line, use multiple lines.
|
||||
- **Do not use TABS**, use 4 spaces instead.
|
||||
- Avoid trailing spaces, please, avoid them
|
||||
- Comments always start with space + capital letter and never end with a '.', place them **before** the line(s) they refer to
|
||||
|
||||
24
README.md
@ -14,14 +14,13 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
|
||||
|
||||
[](https://github.com/raysan5/raylib/releases)
|
||||
[](https://github.com/raysan5/raylib/stargazers)
|
||||
[](https://github.com/raysan5/raylib/commits/master)
|
||||
[](https://github.com/raysan5/raylib/commits/master)
|
||||
[](https://github.com/sponsors/raysan5)
|
||||
[](https://repology.org/project/raylib/versions)
|
||||
[](LICENSE)
|
||||
|
||||
[](https://discord.gg/raylib)
|
||||
[](https://www.reddit.com/r/raylib/)
|
||||
[](https://www.youtube.com/c/raylib)
|
||||
[](https://www.youtube.com/c/raylib)
|
||||
[](https://www.twitch.tv/raysan5)
|
||||
|
||||
[](https://github.com/raysan5/raylib/actions/workflows/build_windows.yml)
|
||||
@ -35,7 +34,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html)
|
||||
|
||||
features
|
||||
--------
|
||||
- **NO external dependencies**, all required libraries are [included into raylib](https://github.com/raysan5/raylib/tree/master/src/external)
|
||||
- **NO external dependencies**, all required libraries are [included in raylib](https://github.com/raysan5/raylib/tree/master/src/external)
|
||||
- Multiple platforms supported: **Windows, Linux, MacOS, RPI, Android, HTML5... and more!**
|
||||
- Written in plain C code (C99) using PascalCase/camelCase notation
|
||||
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
|
||||
@ -50,10 +49,21 @@ features
|
||||
- **Powerful math module** for Vector, Matrix and Quaternion operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.h)
|
||||
- Audio loading and playing with streaming support (WAV, QOA, OGG, MP3, FLAC, XM, MOD)
|
||||
- **VR stereo rendering** support with configurable HMD device parameters
|
||||
- Huge examples collection with [+140 code examples](https://github.com/raysan5/raylib/tree/master/examples)!
|
||||
- Huge examples collection with [+200 code examples](https://github.com/raysan5/raylib/tree/master/examples)!
|
||||
- Bindings to [+70 programming languages](https://github.com/raysan5/raylib/blob/master/BINDINGS.md)!
|
||||
- **Free and open source**
|
||||
|
||||
limitations
|
||||
-----------
|
||||
|
||||
raylib presents some limitations by design for code simplicity. Some forks, alternatives, and samples are available to overcome most of them but it's up to the users to modify the library for their specific needs.
|
||||
|
||||
- Single window with single OpenGL context by default, no multi-window support
|
||||
- Window resize and move stops the rendering loop on platforms supporting a window
|
||||
- `RenderTextures` are flipped vertically, as provided by OpenGL, it's up to the user to draw them flipped to the screen
|
||||
- Font rasterization has lower quality than alternatives using `Freetype2`, `HarfBuzz` or `Slug`
|
||||
- Text drawing does not support RTL, ligatures or emojis
|
||||
|
||||
basic example
|
||||
--------------
|
||||
This is a basic raylib example, it creates a window and draws the text `"Congrats! You created your first window!"` in the middle of the screen. Check this example [running live on web here](https://www.raylib.com/examples/core/loader.html?name=core_basic_window).
|
||||
@ -99,7 +109,7 @@ raylib is also available via multiple package managers on multiple OS distributi
|
||||
- [Working for Web (HTML5)](https://github.com/raysan5/raylib/wiki/Working-for-Web-(HTML5))
|
||||
- [Working anywhere with CMake](https://github.com/raysan5/raylib/wiki/Working-with-CMake)
|
||||
|
||||
*Note that the Wiki is open for edit, if you find some issues while building raylib for your target platform, feel free to edit the Wiki or open an issue related to it.*
|
||||
*Note that the Wiki is open to edits, if you find some issues while building raylib for your target platform, feel free to edit the Wiki or open an issue related to it.*
|
||||
|
||||
#### Setup raylib with multiple IDEs
|
||||
|
||||
@ -112,7 +122,7 @@ raylib has been developed on Windows platform using [Notepad++](https://notepad-
|
||||
learning and docs
|
||||
------------------
|
||||
|
||||
raylib is designed to be learned using [the examples](https://github.com/raysan5/raylib/tree/master/examples) as the main reference. There is no standard API documentation but there is a [**cheatsheet**](https://www.raylib.com/cheatsheet/cheatsheet.html) containing all the functions available on the library a short description of each one of them, input parameters and result value names should be intuitive enough to understand how each function works.
|
||||
raylib is designed to be learned using [the examples](https://github.com/raysan5/raylib/tree/master/examples) as the main reference. There is no standard API documentation but there is a [**cheatsheet**](https://www.raylib.com/cheatsheet/cheatsheet.html) containing all the functions available in the library with a short description of each one; input parameters and result value names should be intuitive enough to understand how each function works.
|
||||
|
||||
Some additional documentation about raylib design can be found in [raylib GitHub Wiki](https://github.com/raysan5/raylib/wiki). Here are the relevant links:
|
||||
|
||||
|
||||
@ -11,8 +11,4 @@ Most considerations of errors and defects can be handled using the project Issue
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Discovered vulnerability can be directly reported using the project Issues and/or Discussions.
|
||||
|
||||
_TODO: Tell them where to go, how often they can expect to get an update on a
|
||||
reported vulnerability, what to expect if the vulnerability is accepted or
|
||||
declined, etc._
|
||||
Discovered vulnerability can be directly reported using the project Issues and/or Discussions. They will be reviewed as soon as possible.
|
||||
|
||||
396
build.zig
@ -2,85 +2,257 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub const emsdk = struct {
|
||||
const zemscripten = @import("zemscripten");
|
||||
const emsdk_version = "4.0.19"; // inline constant used only in activate
|
||||
var emsdk_dep: ?*std.Build.Dependency = null;
|
||||
|
||||
pub fn shell(raylib_dep: *std.Build.Dependency) std.Build.LazyPath {
|
||||
return raylib_dep.path("src/shell.html");
|
||||
}
|
||||
|
||||
pub const FlagsOptions = struct {
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
asyncify: bool = true,
|
||||
// ---------- core types ----------
|
||||
pub const EmccFlags = std.StringHashMap(void);
|
||||
pub const EmccSettings = std.StringHashMap([]const u8);
|
||||
const EmsdkAllocator = enum {
|
||||
none,
|
||||
dlmalloc,
|
||||
emmalloc,
|
||||
@"emmalloc-debug",
|
||||
@"emmalloc-memvalidate",
|
||||
@"emmalloc-verbose",
|
||||
mimalloc,
|
||||
};
|
||||
|
||||
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: FlagsOptions) zemscripten.EmccFlags {
|
||||
var emcc_flags = zemscripten.emccDefaultFlags(allocator, .{
|
||||
.optimize = options.optimize,
|
||||
.fsanitize = true,
|
||||
});
|
||||
pub const ResourceFile = struct {
|
||||
src_path: std.Build.LazyPath,
|
||||
virtual_path: ?[]const u8 = null,
|
||||
|
||||
if (options.asyncify)
|
||||
emcc_flags.put("-sASYNCIFY", {}) catch unreachable;
|
||||
fn get(self: ResourceFile, b: *std.Build) []const u8 {
|
||||
return if (self.virtual_path) |vp|
|
||||
b.fmt("{s}@{s}", .{ self.src_path.getDisplayName(), vp })
|
||||
else
|
||||
self.src_path.getDisplayName();
|
||||
}
|
||||
};
|
||||
|
||||
return emcc_flags;
|
||||
pub const EmccStepOptions = struct {
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
flags: EmccFlags,
|
||||
settings: EmccSettings,
|
||||
use_preload_plugins: bool = false,
|
||||
embed_paths: ?[]const ResourceFile = null,
|
||||
preload_paths: ?[]const ResourceFile = null,
|
||||
shell_file_path: ?std.Build.LazyPath = null,
|
||||
js_library_path: ?std.Build.LazyPath = null,
|
||||
out_file_name: []const u8,
|
||||
install_dir: std.Build.InstallDir,
|
||||
};
|
||||
|
||||
// ---------- helpers ----------
|
||||
pub fn emsdkDep(b: *std.Build) !*std.Build.Dependency {
|
||||
if (emsdk_dep == null) {
|
||||
emsdk_dep = try b.dependencyLazy("emsdk", .{});
|
||||
}
|
||||
|
||||
return emsdk_dep.?;
|
||||
}
|
||||
|
||||
pub const SettingsOptions = struct {
|
||||
pub fn path(b: *std.Build, sub_path: []const u8) !std.Build.LazyPath {
|
||||
return (try emsdkDep(b)).path(sub_path);
|
||||
}
|
||||
|
||||
pub fn emccPath(b: *std.Build) !std.Build.LazyPath {
|
||||
return try emsdk.path(b, "upstream/emscripten/emcc.py");
|
||||
}
|
||||
|
||||
pub fn emrunPath(b: *std.Build) !std.Build.LazyPath {
|
||||
return switch (builtin.target.os.tag) {
|
||||
.windows => try emsdk.path(b, "upstream/emscripten/emrun.bat"),
|
||||
else => try emsdk.path(b, "upstream/emscripten/emrun"),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn emccDefaultFlags(allocator: std.mem.Allocator, options: struct {
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
asyncify: bool = true,
|
||||
fsanitize: bool = true,
|
||||
}) EmccFlags {
|
||||
var flags = EmccFlags.init(allocator);
|
||||
switch (options.optimize) {
|
||||
.Debug => {
|
||||
flags.put("-O0", {}) catch @panic("OOM");
|
||||
flags.put("-gsource-map", {}) catch @panic("OOM");
|
||||
if (options.fsanitize)
|
||||
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
|
||||
},
|
||||
.ReleaseSafe => {
|
||||
flags.put("-O3", {}) catch @panic("OOM");
|
||||
if (options.fsanitize) {
|
||||
flags.put("-fsanitize=undefined", {}) catch @panic("OOM");
|
||||
flags.put("-fsanitize-minimal-runtime", {}) catch @panic("OOM");
|
||||
}
|
||||
},
|
||||
.ReleaseFast => flags.put("-O3", {}) catch @panic("OOM"),
|
||||
.ReleaseSmall => flags.put("-Oz", {}) catch @panic("OOM"),
|
||||
}
|
||||
if (options.asyncify)
|
||||
flags.put("-sASYNCIFY", {}) catch @panic("OOM");
|
||||
return flags;
|
||||
}
|
||||
|
||||
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: struct {
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
es3: bool = false,
|
||||
glfw3: bool = true,
|
||||
memory_growth: bool = false,
|
||||
total_memory: u32 = 134217728,
|
||||
emsdk_allocator: zemscripten.EmsdkAllocator = .emmalloc,
|
||||
};
|
||||
|
||||
pub fn emccDefaultSettings(allocator: std.mem.Allocator, options: SettingsOptions) zemscripten.EmccSettings {
|
||||
var emcc_settings = zemscripten.emccDefaultSettings(allocator, .{
|
||||
.optimize = options.optimize,
|
||||
.emsdk_allocator = options.emsdk_allocator,
|
||||
});
|
||||
emsdk_allocator: EmsdkAllocator = .emmalloc,
|
||||
}) EmccSettings {
|
||||
var settings = EmccSettings.init(allocator);
|
||||
switch (options.optimize) {
|
||||
.Debug, .ReleaseSafe => {
|
||||
settings.put("SAFE_HEAP", "1") catch @panic("OOM");
|
||||
settings.put("STACK_OVERFLOW_CHECK", "1") catch @panic("OOM");
|
||||
settings.put("ASSERTIONS", "1") catch @panic("OOM");
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
settings.put("MALLOC", @tagName(options.emsdk_allocator)) catch @panic("OOM");
|
||||
|
||||
if (options.es3) {
|
||||
emcc_settings.put("FULL_ES3", "1") catch unreachable;
|
||||
emcc_settings.put("MIN_WEBGL_VERSION", "2") catch unreachable;
|
||||
emcc_settings.put("MAX_WEBGL_VERSION", "2") catch unreachable;
|
||||
}
|
||||
if (options.glfw3) {
|
||||
emcc_settings.put("USE_GLFW", "3") catch unreachable;
|
||||
settings.put("FULL_ES3", "1") catch @panic("OOM");
|
||||
settings.put("MIN_WEBGL_VERSION", "2") catch @panic("OOM");
|
||||
settings.put("MAX_WEBGL_VERSION", "2") catch @panic("OOM");
|
||||
}
|
||||
if (options.glfw3)
|
||||
settings.put("USE_GLFW", "3") catch @panic("OOM");
|
||||
|
||||
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch unreachable;
|
||||
|
||||
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch unreachable;
|
||||
emcc_settings.put("TOTAL_MEMORY", total_memory) catch unreachable;
|
||||
emcc_settings.put("FORCE_FILESYSTEM", "1") catch unreachable;
|
||||
emcc_settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch unreachable;
|
||||
const total_memory = std.fmt.allocPrint(allocator, "{d}", .{options.total_memory}) catch @panic("OOM");
|
||||
settings.put("EXPORTED_RUNTIME_METHODS", "['requestFullscreen']") catch @panic("OOM");
|
||||
settings.put("TOTAL_MEMORY", total_memory) catch @panic("OOM");
|
||||
settings.put("FORCE_FILESYSTEM", "1") catch @panic("OOM");
|
||||
settings.put("EXPORTED_RUNTIME_METHODS", "ccall") catch @panic("OOM");
|
||||
|
||||
if (options.memory_growth)
|
||||
emcc_settings.put("ALLOW_MEMORY_GROWTH", "1") catch unreachable;
|
||||
settings.put("ALLOW_MEMORY_GROWTH", "1") catch @panic("OOM");
|
||||
|
||||
return emcc_settings;
|
||||
return settings;
|
||||
}
|
||||
|
||||
pub fn emccStep(b: *std.Build, raylib: *std.Build.Step.Compile, wasm: *std.Build.Step.Compile, options: zemscripten.StepOptions) *std.Build.Step {
|
||||
const activate_emsdk_step = zemscripten.activateEmsdkStep(b);
|
||||
// ---------- step builders ----------
|
||||
pub fn emccStep(b: *std.Build, src_paths: []const std.Build.LazyPath, compile_steps: []const *std.Build.Step.Compile, options: EmccStepOptions) !*std.Build.Step {
|
||||
var emcc = b.addRunFile(try emccPath(b));
|
||||
|
||||
const emsdk_dep = b.dependency("emsdk", .{});
|
||||
raylib.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
|
||||
wasm.root_module.addIncludePath(emsdk_dep.path("upstream/emscripten/cache/sysroot/include"));
|
||||
// flags
|
||||
{
|
||||
var it = options.flags.iterator();
|
||||
while (it.next()) |kv| emcc.addArg(kv.key_ptr.*);
|
||||
}
|
||||
|
||||
const emcc_step = zemscripten.emccStep(b, wasm, options);
|
||||
emcc_step.dependOn(activate_emsdk_step);
|
||||
// settings
|
||||
{
|
||||
var it = options.settings.iterator();
|
||||
while (it.next()) |kv| {
|
||||
emcc.addArg(b.fmt("-s{s}={s}", .{ kv.key_ptr.*, kv.value_ptr.* }));
|
||||
}
|
||||
}
|
||||
|
||||
return emcc_step;
|
||||
// source files & artifact dependencies
|
||||
for (src_paths) |sp| emcc.addFileArg(sp);
|
||||
for (compile_steps) |cs| {
|
||||
emcc.addArtifactArg(cs);
|
||||
cs.root_module.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
|
||||
for (cs.root_module.getGraph().modules) |mod| {
|
||||
for (mod.link_objects.items) |lo| {
|
||||
if (lo == .other_step) {
|
||||
const linked = lo.other_step;
|
||||
if (linked.kind == .lib) emcc.addArtifactArg(linked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emcc.addArg("-o");
|
||||
const out_file = emcc.addOutputFileArg(options.out_file_name);
|
||||
|
||||
// optional args
|
||||
if (options.use_preload_plugins) emcc.addArg("--use-preload-plugins");
|
||||
if (options.embed_paths) |eps| for (eps) |ep| {
|
||||
emcc.addArg("--embed-file");
|
||||
emcc.addFileArg(ep.src_path);
|
||||
};
|
||||
if (options.preload_paths) |pps| for (pps) |pp| {
|
||||
emcc.addArg("--preload-file");
|
||||
emcc.addArg(pp.get(b));
|
||||
};
|
||||
if (options.shell_file_path) |sfp| {
|
||||
emcc.addArg("--shell-file");
|
||||
emcc.addFileArg(sfp);
|
||||
}
|
||||
if (options.js_library_path) |jlp| {
|
||||
emcc.addArg("--js-library");
|
||||
emcc.addFileArg(jlp);
|
||||
}
|
||||
|
||||
const install = b.addInstallDirectory(.{
|
||||
.source_dir = out_file.dirname(),
|
||||
.install_dir = options.install_dir,
|
||||
.install_subdir = "",
|
||||
});
|
||||
install.step.dependOn(&emcc.step);
|
||||
return &install.step;
|
||||
}
|
||||
|
||||
pub fn emrunStep(
|
||||
b: *std.Build,
|
||||
html_path: []const u8,
|
||||
extra_args: []const []const u8,
|
||||
) *std.Build.Step {
|
||||
return zemscripten.emrunStep(b, html_path, extra_args);
|
||||
pub fn emrunStep(b: *std.Build, html_path: std.Build.LazyPath, extra_args: []const []const u8) !*std.Build.Step {
|
||||
var emrun = b.addRunFile(try emrunPath(b));
|
||||
emrun.addArgs(extra_args);
|
||||
emrun.addFileArg(html_path);
|
||||
return &emrun.step;
|
||||
}
|
||||
|
||||
pub fn activateEmsdkStep(b: *std.Build) !*std.Build.Step {
|
||||
const user = b.step("Activate EMSDK", "Install/Update and prepare emscripten sdk");
|
||||
const script = switch (builtin.target.os.tag) {
|
||||
.windows => try emsdk.path(b, "emsdk.bat"),
|
||||
else => try emsdk.path(b, "emsdk"),
|
||||
};
|
||||
|
||||
var update = b.addRunFile(script);
|
||||
update.addArg("update");
|
||||
|
||||
// chmod / takeown for script
|
||||
const make_script_exec: ?*std.Build.Step.Run = switch (builtin.target.os.tag) {
|
||||
.linux, .macos => blk: {
|
||||
var cmd = b.addSystemCommand(&.{ "chmod", "+x" });
|
||||
cmd.addFileArg(script);
|
||||
break :blk cmd;
|
||||
},
|
||||
.windows => blk: {
|
||||
var cmd = b.addSystemCommand(&.{ "takeown", "/f" });
|
||||
cmd.addFileArg(script);
|
||||
break :blk cmd;
|
||||
},
|
||||
else => null,
|
||||
};
|
||||
if (make_script_exec) |mse| update.step.dependOn(&mse.step);
|
||||
|
||||
var install = b.addRunFile(script);
|
||||
install.addArg("install");
|
||||
install.addArg(emsdk_version);
|
||||
install.step.dependOn(&update.step);
|
||||
|
||||
var activate = b.addRunFile(script);
|
||||
activate.addArg("activate");
|
||||
activate.addArg(emsdk_version);
|
||||
activate.step.dependOn(&install.step);
|
||||
user.dependOn(&activate.step);
|
||||
|
||||
// also ensure emcc/emrun are executable on Unix
|
||||
if (builtin.target.os.tag == .linux or builtin.target.os.tag == .macos) {
|
||||
for ([_]std.Build.LazyPath{ try emccPath(b), try emrunPath(b) }) |p| {
|
||||
var cmd = b.addSystemCommand(&.{ "chmod", "a+x" });
|
||||
cmd.addFileArg(p);
|
||||
cmd.step.dependOn(&install.step);
|
||||
user.dependOn(&cmd.step);
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
};
|
||||
|
||||
@ -92,7 +264,7 @@ pub fn linkWindows(mod: *std.Build.Module, opengl: bool, comptime shcore: bool)
|
||||
}
|
||||
|
||||
fn findWaylandScanner(b: *std.Build) void {
|
||||
_ = b.findProgram(&.{"wayland-scanner"}, &.{}) catch {
|
||||
_ = b.findProgram(.{ .names = &.{"wayland-scanner"} }) orelse {
|
||||
std.log.err(
|
||||
\\ `wayland-scanner` may not be installed on the system.
|
||||
\\ You can switch to X11 in your `build.zig` by changing `Options.linux_display_backend`
|
||||
@ -126,19 +298,20 @@ pub fn linkBSD(_: *std.Build, mod: *std.Build.Module) void {
|
||||
mod.linkSystemLibrary("GL", .{});
|
||||
}
|
||||
|
||||
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) void {
|
||||
pub fn linkMacOS(b: *std.Build, mod: *std.Build.Module) !void {
|
||||
// Include xcode_frameworks for cross compilation
|
||||
if (b.lazyDependency("xcode_frameworks", .{})) |dep| {
|
||||
mod.addSystemFrameworkPath(dep.path("Frameworks"));
|
||||
mod.addSystemIncludePath(dep.path("include"));
|
||||
mod.addLibraryPath(dep.path("lib"));
|
||||
}
|
||||
const dep = try b.dependencyLazy("xcode_frameworks", .{});
|
||||
|
||||
mod.addSystemFrameworkPath(dep.path("Frameworks"));
|
||||
mod.addSystemIncludePath(dep.path("include"));
|
||||
mod.addLibraryPath(dep.path("lib"));
|
||||
|
||||
mod.linkFramework("Foundation", .{});
|
||||
mod.linkFramework("CoreServices", .{});
|
||||
mod.linkFramework("CoreGraphics", .{});
|
||||
mod.linkFramework("AppKit", .{});
|
||||
mod.linkFramework("IOKit", .{});
|
||||
mod.linkFramework("QuartzCore", .{});
|
||||
}
|
||||
|
||||
fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, options: Options) !*std.Build.Step.Compile {
|
||||
@ -154,7 +327,13 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||
.root_module = raylib_mod,
|
||||
});
|
||||
|
||||
raylib_mod.addCMacro("_GNU_SOURCE", "");
|
||||
// On Linux (glibc) avoid _GNU_SOURCE, on glibc >= 2.38 it redirects sscanf(), strtol()...
|
||||
// to __isoc23_*() symbols, so the generated library fails to link with older glibc versions
|
||||
if (target.result.os.tag == .linux and !target.result.abi.isAndroid()) {
|
||||
raylib_mod.addCMacro("_DEFAULT_SOURCE", "");
|
||||
} else {
|
||||
raylib_mod.addCMacro("_GNU_SOURCE", "");
|
||||
}
|
||||
raylib_mod.addCMacro("GL_SILENCE_DEPRECATION", "199309L");
|
||||
|
||||
var arena: std.heap.ArenaAllocator = .init(b.allocator);
|
||||
@ -261,7 +440,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||
});
|
||||
_ = raylib_flags_arr.pop();
|
||||
|
||||
linkMacOS(b, raylib_mod);
|
||||
try linkMacOS(b, raylib_mod);
|
||||
},
|
||||
.emscripten => {
|
||||
switch (opengl_version) {
|
||||
@ -272,7 +451,9 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_WEB", "");
|
||||
|
||||
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
|
||||
raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
|
||||
|
||||
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
|
||||
raylib.step.dependOn(activate_emsdk_step);
|
||||
},
|
||||
else => @panic("Target is not supported with this platform"),
|
||||
@ -321,7 +502,7 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||
}
|
||||
},
|
||||
.freebsd, .openbsd, .netbsd, .dragonfly => linkBSD(b, raylib_mod),
|
||||
.macos => linkMacOS(b, raylib_mod),
|
||||
.macos => try linkMacOS(b, raylib_mod),
|
||||
.emscripten => {
|
||||
switch (opengl_version) {
|
||||
.auto => opengl_version = OpenglVersion.gles_2,
|
||||
@ -330,7 +511,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||
}
|
||||
|
||||
raylib_mod.addCMacro("PLATFORM_WEB_RGFW", "");
|
||||
const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
|
||||
|
||||
raylib_mod.addIncludePath(try emsdk.path(b, "upstream/emscripten/cache/sysroot/include"));
|
||||
|
||||
const activate_emsdk_step = try emsdk.activateEmsdkStep(b);
|
||||
raylib.step.dependOn(activate_emsdk_step);
|
||||
},
|
||||
else => @panic("Target is not supported with this platform"),
|
||||
@ -476,33 +660,33 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
||||
return raylib;
|
||||
}
|
||||
|
||||
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) void {
|
||||
if (b.lazyDependency("raygui", .{
|
||||
fn addRaygui(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, raylib: *std.Build.Step.Compile) !void {
|
||||
const raygui_dep = try b.dependencyLazy("raygui", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
})) |raygui_dep| {
|
||||
var gen_step = b.addWriteFiles();
|
||||
raylib.step.dependOn(&gen_step.step);
|
||||
});
|
||||
|
||||
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
|
||||
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
|
||||
raylib.root_module.addIncludePath(raygui_dep.path("src"));
|
||||
raylib.root_module.addIncludePath(b.path("src"));
|
||||
var gen_step = b.addWriteFiles();
|
||||
raylib.step.dependOn(&gen_step.step);
|
||||
|
||||
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
|
||||
const raygui_c_path = gen_step.add("raygui.c", "#define RAYGUI_IMPLEMENTATION\n#include \"raygui.h\"\n");
|
||||
raylib.root_module.addCSourceFile(.{ .file = raygui_c_path });
|
||||
raylib.root_module.addIncludePath(raygui_dep.path("src"));
|
||||
raylib.root_module.addIncludePath(b.path("src"));
|
||||
|
||||
const c = b.addTranslateC(.{
|
||||
.root_source_file = raygui_dep.path("src/raygui.h"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
c.addIncludePath(b.path("src"));
|
||||
const c_mod = c.createModule();
|
||||
c_mod.linkLibrary(raylib);
|
||||
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
|
||||
}
|
||||
raylib.installHeader(raygui_dep.path("src/raygui.h"), "raygui.h");
|
||||
|
||||
const c = b.addTranslateC(.{
|
||||
.root_source_file = raygui_dep.path("src/raygui.h"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.link_libc = true,
|
||||
});
|
||||
c.addIncludePath(b.path("src"));
|
||||
const c_mod = c.createModule();
|
||||
c_mod.linkLibrary(raylib);
|
||||
b.modules.put(b.graph.arena, "raygui", c_mod) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub const Options = struct {
|
||||
@ -623,7 +807,7 @@ pub fn build(b: *std.Build) !void {
|
||||
translateCMod("rlgl", b, target, optimize, lib);
|
||||
|
||||
if (options.raygui) {
|
||||
addRaygui(b, target, optimize, lib);
|
||||
try addRaygui(b, target, optimize, lib);
|
||||
}
|
||||
|
||||
const examples = b.step("examples", "build/install all examples");
|
||||
@ -648,7 +832,7 @@ fn addExamples(
|
||||
const all = b.step(module, "All " ++ module ++ " examples");
|
||||
const module_subpath = b.pathJoin(&.{ "examples", module });
|
||||
|
||||
var dir = try b.build_root.handle.openDir(b.graph.io, module_subpath, .{ .iterate = true });
|
||||
var dir = try b.root.openDir(b.graph.io, module_subpath, .{ .iterate = true });
|
||||
defer dir.close(b.graph.io);
|
||||
|
||||
var iter = dir.iterate();
|
||||
@ -698,7 +882,7 @@ fn addExamples(
|
||||
exe_mod.addCMacro("PLATFORM_WEB", "");
|
||||
|
||||
const wasm = b.addLibrary(.{
|
||||
.name = filename,
|
||||
.name = b.fmt("{s}.html", .{filename}),
|
||||
.root_module = exe_mod,
|
||||
});
|
||||
|
||||
@ -706,19 +890,40 @@ fn addExamples(
|
||||
const emcc_flags = emsdk.emccDefaultFlags(b.allocator, .{ .optimize = optimize });
|
||||
const emcc_settings = emsdk.emccDefaultSettings(b.allocator, .{ .optimize = optimize });
|
||||
|
||||
const emcc_step = emsdk.emccStep(b, raylib, wasm, .{
|
||||
const SerialResourceFile = struct { src_path: []const u8, virtual_path: []const u8 };
|
||||
const EmccExamplesPreloadMap = std.static_string_map.StaticStringMap([]const SerialResourceFile);
|
||||
const EmccExamplesPreloadSerial = struct { []const u8, []const SerialResourceFile };
|
||||
const emcc_examples_preloads_serial: []const EmccExamplesPreloadSerial = @import("examples/example_resources.zon");
|
||||
const emcc_examples_preloads_map = EmccExamplesPreloadMap.initComptime(emcc_examples_preloads_serial);
|
||||
const preload_paths: ?[]emsdk.ResourceFile = blk: {
|
||||
if (emcc_examples_preloads_map.get(filename)) |resource_files| {
|
||||
var rfs = try b.allocator.alloc(emsdk.ResourceFile, resource_files.len);
|
||||
for (resource_files, 0..) |resource_file, rfidx| {
|
||||
rfs[rfidx] = .{
|
||||
.src_path = b.path(resource_file.src_path),
|
||||
.virtual_path = resource_file.virtual_path,
|
||||
};
|
||||
}
|
||||
break :blk rfs;
|
||||
} else break :blk null;
|
||||
};
|
||||
|
||||
const emcc_step = try emsdk.emccStep(b, &.{}, &.{ raylib, wasm }, .{
|
||||
.optimize = optimize,
|
||||
.flags = emcc_flags,
|
||||
.settings = emcc_settings,
|
||||
.preload_paths = preload_paths,
|
||||
.shell_file_path = b.path("src/shell.html"),
|
||||
.install_dir = install_dir,
|
||||
.out_file_name = wasm.name,
|
||||
});
|
||||
b.getInstallStep().dependOn(emcc_step);
|
||||
|
||||
const html_filename = try std.fmt.allocPrint(b.allocator, "{s}.html", .{wasm.name});
|
||||
const emrun_step = emsdk.emrunStep(
|
||||
const emrun_step = try emsdk.emrunStep(
|
||||
b,
|
||||
b.getInstallPath(install_dir, html_filename),
|
||||
b.graph.path(.install_prefix, b.fmt(
|
||||
"web/{s}/{s}/{s}",
|
||||
.{ module, filename, wasm.name },
|
||||
)),
|
||||
&.{},
|
||||
);
|
||||
|
||||
@ -733,7 +938,6 @@ fn addExamples(
|
||||
.root_module = exe_mod,
|
||||
.use_lld = target.result.os.tag == .windows,
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
|
||||
const install_cmd = b.addInstallArtifact(exe, .{ .dest_sub_path = b.fmt("{s}/{s}", .{ module, filename }) });
|
||||
|
||||
@ -754,7 +958,7 @@ fn waylandGenerate(
|
||||
comptime waylandDir: []const u8,
|
||||
comptime source: bool,
|
||||
) !void {
|
||||
const dir = try b.build_root.handle.openDir(b.graph.io, waylandDir, .{ .iterate = true });
|
||||
const dir = try b.root.openDir(b.graph.io, waylandDir, .{ .iterate = true });
|
||||
defer dir.close(b.graph.io);
|
||||
|
||||
var iter = dir.iterate();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
.{
|
||||
.name = .raylib,
|
||||
.version = "6.0.0",
|
||||
.minimum_zig_version = "0.16.0",
|
||||
.minimum_zig_version = "0.17.0",
|
||||
|
||||
.fingerprint = 0x13035e5cb8bc1ac2, // Changing this has security and trust implications.
|
||||
|
||||
@ -12,17 +12,14 @@
|
||||
.lazy = true,
|
||||
},
|
||||
.raygui = .{
|
||||
.url = "git+https://github.com/raysan5/raygui#3b2855842ab578a034f827c38cf8f62c042fc983",
|
||||
.hash = "N-V-__8AAHvybwBw1kyBGn0BW_s1RqIpycNjLf_XbE-fpLUF",
|
||||
.url = "git+https://github.com/raysan5/raygui#3f81e2bd02bf08dcd9d350e8e8b3cf58044d6877",
|
||||
.hash = "N-V-__8AAPPCmABYkTrLoRGTR6whFQP1bvg7p5vpLsKIcn4G",
|
||||
.lazy = true,
|
||||
},
|
||||
.emsdk = .{
|
||||
.url = "git+https://github.com/emscripten-core/emsdk#4.0.9",
|
||||
.hash = "N-V-__8AAJl1DwBezhYo_VE6f53mPVm00R-Fk28NPW7P14EQ",
|
||||
},
|
||||
.zemscripten = .{
|
||||
.url = "git+https://github.com/zig-gamedev/zemscripten#3fa4b778852226c7346bdcc3c1486e875a9a6d02",
|
||||
.hash = "zemscripten-0.2.0-dev-sRlDqApRAACspTbAZnuNKWIzfWzSYgYkb2nWAXZ-tqqt",
|
||||
.lazy = true,
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@ -7,6 +7,30 @@ if(POLICY CMP0072)
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
endif()
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
include(CMakePushCheckState)
|
||||
|
||||
function(raylib_check_libatomic_required result)
|
||||
set(_atomic_test_source "
|
||||
int main(void)
|
||||
{
|
||||
volatile long long value = 0;
|
||||
return (int)__atomic_fetch_add(&value, 1, __ATOMIC_SEQ_CST);
|
||||
}")
|
||||
|
||||
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||
|
||||
if (RAYLIB_ATOMICS_WITHOUT_LIBATOMIC)
|
||||
set(${result} FALSE PARENT_SCOPE)
|
||||
else ()
|
||||
cmake_push_check_state()
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES atomic)
|
||||
check_c_source_compiles("${_atomic_test_source}" RAYLIB_ATOMICS_WITH_LIBATOMIC)
|
||||
cmake_pop_check_state()
|
||||
set(${result} ${RAYLIB_ATOMICS_WITH_LIBATOMIC} PARENT_SCOPE)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
set(RAYLIB_DEPENDENCIES "include(CMakeFindDependencyMacro)")
|
||||
|
||||
if (${PLATFORM} STREQUAL "Desktop")
|
||||
@ -67,6 +91,21 @@ if (${PLATFORM} STREQUAL "Desktop")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
elseif (${PLATFORM} STREQUAL "Win32")
|
||||
if ((NOT WIN32) AND (NOT CMAKE_C_COMPILER MATCHES "mingw|mingw32|mingw64"))
|
||||
message(FATAL_ERROR "Win32 platform requires Windows or a cross compiler.")
|
||||
endif ()
|
||||
|
||||
set(PLATFORM_CPP "PLATFORM_DESKTOP_WIN32")
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if (${OPENGL_VERSION} MATCHES "Software")
|
||||
set(GRAPHICS "GRAPHICS_API_OPENGL_SOFTWARE")
|
||||
endif ()
|
||||
|
||||
find_package(OpenGL QUIET)
|
||||
set(LIBS_PRIVATE ${OPENGL_LIBRARIES} winmm)
|
||||
|
||||
elseif (${PLATFORM} STREQUAL "Web")
|
||||
set(PLATFORM_CPP "PLATFORM_WEB")
|
||||
if(NOT GRAPHICS)
|
||||
@ -222,6 +261,14 @@ endif ()
|
||||
|
||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} ${OPENAL_LIBRARY})
|
||||
|
||||
if (SUPPORT_MODULE_RAUDIO AND UNIX AND NOT APPLE)
|
||||
raylib_check_libatomic_required(RAYLIB_LIBATOMIC_REQUIRED)
|
||||
if (RAYLIB_LIBATOMIC_REQUIRED)
|
||||
message(STATUS "64-bit atomics require libatomic")
|
||||
list(APPEND LIBS_PRIVATE atomic)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (${PLATFORM} MATCHES "Desktop")
|
||||
set(LIBS_PRIVATE ${LIBS_PRIVATE} glfw)
|
||||
endif ()
|
||||
|
||||
@ -10,7 +10,9 @@ string(REGEX MATCHALL ${MACRO_REGEX} MACRO_LIST ${CONFIG_HEADER_CONTENT})
|
||||
set(CONFIG_HEADER_FLAGS ${MACRO_LIST})
|
||||
list(FILTER CONFIG_HEADER_FLAGS INCLUDE REGEX "^.+SUPPORT_")
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=OFF]] REGEX "^//")
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=ON]])
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE ${MACRO_REGEX} [[\2=\3]] REGEX "^[^/]")
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=0$]] [[=OFF]])
|
||||
list(TRANSFORM CONFIG_HEADER_FLAGS REPLACE [[=1$]] [[=ON]])
|
||||
|
||||
set(CONFIG_HEADER_VALUES ${MACRO_LIST})
|
||||
list(FILTER CONFIG_HEADER_VALUES EXCLUDE REGEX "(^.+SUPPORT_)|(^//)")
|
||||
|
||||
@ -1,6 +1,18 @@
|
||||
# Setup the project and settings
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
project(examples)
|
||||
|
||||
# Include raylib's cmake helper functions, so the examples can also be
|
||||
# configured standalone (`cd examples && cmake .`) and not only as part
|
||||
# of the raylib project.
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
|
||||
include(AddIfFlagCompiles)
|
||||
|
||||
# Default to the Desktop platform when configured standalone.
|
||||
if (NOT DEFINED PLATFORM)
|
||||
set(PLATFORM "Desktop" CACHE STRING "Platform to build examples for")
|
||||
endif ()
|
||||
|
||||
# Directories that contain examples
|
||||
set(example_dirs
|
||||
audio
|
||||
@ -98,7 +110,6 @@ if (${PLATFORM} MATCHES "Android")
|
||||
|
||||
elseif (${PLATFORM} MATCHES "Web")
|
||||
set(example_sources) # clear example_sources
|
||||
list(APPEND example_sources others/web_basic_window.c)
|
||||
list(APPEND example_sources core/core_input_gestures_testbed.c)
|
||||
|
||||
elseif ("${PLATFORM}" STREQUAL "DRM")
|
||||
@ -190,6 +201,7 @@ foreach (example_source ${example_sources})
|
||||
target_link_libraries(${example_name} "-framework IOKit")
|
||||
target_link_libraries(${example_name} "-framework Cocoa")
|
||||
target_link_libraries(${example_name} "-framework OpenGL")
|
||||
target_link_libraries(${example_name} "-framework QuartzCore")
|
||||
endif()
|
||||
|
||||
elseif (${PLATFORM} MATCHES "RGFW")
|
||||
|
||||
@ -18,8 +18,10 @@
|
||||
# > PLATFORM_DESKTOP_RGFW (RGFW backend):
|
||||
# - Windows (Win32, Win64)
|
||||
# - Linux (X11 desktop mode)
|
||||
# - macOS/OSX (x64, arm64 (not tested))
|
||||
# - macOS/OSX (x64, arm64)
|
||||
# - Others (not tested)
|
||||
# > PLATFORM_DESKTOP_WIN32 (native Win32):
|
||||
# - Windows (Win32, Win64)
|
||||
# > PLATFORM_WEB_RGFW:
|
||||
# - HTML5 (WebAssembly)
|
||||
# > PLATFORM_WEB:
|
||||
@ -120,6 +122,14 @@ BUILD_WEB_RESOURCES_PATH ?= $(dir $<)resources@resources
|
||||
# WARNING: Requires raylib compiled with GRAPHICS_API_OPENGL_ES3
|
||||
BUILD_WEB_WEBGL2 ?= FALSE
|
||||
|
||||
# Detect the shell used by make: cmd preserves quotes, while sh removes them.
|
||||
ifndef PLATFORM_SHELL
|
||||
PLATFORM_SHELL = sh
|
||||
ifeq ($(shell echo "test"),"test")
|
||||
PLATFORM_SHELL = cmd
|
||||
endif
|
||||
endif
|
||||
|
||||
# Determine PLATFORM_OS when required
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
# No uname.exe on MinGW!, but OS=Windows_NT on Windows!
|
||||
@ -312,6 +322,9 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
LDFLAGS += -Lsrc -L$(RAYLIB_LIB_PATH)
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
LDFLAGS += -L/opt/homebrew/lib -L$(RAYLIB_LIB_PATH)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
@ -416,7 +429,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
# Libraries for OSX 10.9 desktop compiling
|
||||
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
|
||||
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
|
||||
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo -framework QuartzCore
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
|
||||
@ -494,7 +507,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
|
||||
# NOTE: Required packages: libegl1-mesa-dev
|
||||
LDFLAGS += -L../src
|
||||
LDLIBS = -lraylib -lm
|
||||
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo
|
||||
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo -framework QuartzCore
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
@ -587,10 +600,12 @@ SHAPES = \
|
||||
shapes/shapes_dashed_line \
|
||||
shapes/shapes_digital_clock \
|
||||
shapes/shapes_double_pendulum \
|
||||
shapes/shapes_drag_puzzle \
|
||||
shapes/shapes_easings_ball \
|
||||
shapes/shapes_easings_box \
|
||||
shapes/shapes_easings_rectangles \
|
||||
shapes/shapes_easings_testbed \
|
||||
shapes/shapes_ellipse_collision \
|
||||
shapes/shapes_following_eyes \
|
||||
shapes/shapes_hilbert_curve \
|
||||
shapes/shapes_kaleidoscope \
|
||||
@ -601,8 +616,11 @@ SHAPES = \
|
||||
shapes/shapes_math_angle_rotation \
|
||||
shapes/shapes_math_sine_cosine \
|
||||
shapes/shapes_mouse_trail \
|
||||
shapes/shapes_outlines_testbed \
|
||||
shapes/shapes_outlines_thickness \
|
||||
shapes/shapes_penrose_tile \
|
||||
shapes/shapes_pie_chart \
|
||||
shapes/shapes_polygon_lines \
|
||||
shapes/shapes_rectangle_advanced \
|
||||
shapes/shapes_rectangle_scaling \
|
||||
shapes/shapes_recursive_tree \
|
||||
@ -640,6 +658,7 @@ TEXTURES = \
|
||||
textures/textures_npatch_drawing \
|
||||
textures/textures_particles_blending \
|
||||
textures/textures_polygon_drawing \
|
||||
textures/textures_portal_window \
|
||||
textures/textures_raw_data \
|
||||
textures/textures_screen_buffer \
|
||||
textures/textures_sprite_animation \
|
||||
@ -691,8 +710,10 @@ MODELS = \
|
||||
models/models_loading_vox \
|
||||
models/models_mesh_generation \
|
||||
models/models_mesh_picking \
|
||||
models/models_mesh_uv_painting \
|
||||
models/models_orthographic_projection \
|
||||
models/models_point_rendering \
|
||||
models/models_procedural_decals \
|
||||
models/models_rlgl_solar_system \
|
||||
models/models_rotating_cube \
|
||||
models/models_skybox_rendering \
|
||||
@ -718,6 +739,7 @@ SHADERS = \
|
||||
shaders/shaders_hybrid_rendering \
|
||||
shaders/shaders_julia_set \
|
||||
shaders/shaders_lightmap_rendering \
|
||||
shaders/shaders_lights_bloom \
|
||||
shaders/shaders_mandelbrot_set \
|
||||
shaders/shaders_mesh_instancing \
|
||||
shaders/shaders_model_shader \
|
||||
@ -739,6 +761,7 @@ SHADERS = \
|
||||
shaders/shaders_vertex_displacement
|
||||
|
||||
AUDIO = \
|
||||
audio/audio_amp_envelope \
|
||||
audio/audio_mixed_processor \
|
||||
audio/audio_module_playing \
|
||||
audio/audio_music_stream \
|
||||
@ -779,7 +802,32 @@ endif
|
||||
clean:
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
ifeq ($(PLATFORM_SHELL),cmd)
|
||||
del *.o *.exe /s
|
||||
else
|
||||
find . -type f '(' -name '*.o' -o -name '*.exe' ')' -exec rm -f {} +
|
||||
endif
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
find . -type f -perm -ugo+x -delete
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),LINUX)
|
||||
find . -type f -executable -delete
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
find . -type f -perm +ugo+x -delete
|
||||
rm -f *.o
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32)
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
ifeq ($(PLATFORM_SHELL),cmd)
|
||||
del *.o *.exe /s
|
||||
else
|
||||
find . -type f '(' -name '*.o' -o -name '*.exe' ')' -exec rm -f {} +
|
||||
endif
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
find . -type f -perm -ugo+x -delete
|
||||
@ -799,7 +847,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
rm -fv *.o
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW))
|
||||
ifeq ($(PLATFORM_OS),WINDOWS)
|
||||
ifeq ($(PLATFORM_SHELL),cmd)
|
||||
del *.wasm *.html *.js *.data
|
||||
else
|
||||
rm -f */*.wasm */*.html */*.js */*.data
|
||||
|
||||
@ -411,7 +411,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
|
||||
ifeq ($(PLATFORM_OS),OSX)
|
||||
# Libraries for OSX 10.9 desktop compiling
|
||||
# NOTE: Required packages: libopenal-dev libegl1-mesa-dev
|
||||
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
|
||||
LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo -framework QuartzCore
|
||||
endif
|
||||
ifeq ($(PLATFORM_OS),BSD)
|
||||
# Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
|
||||
@ -480,7 +480,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
|
||||
# NOTE: Required packages: libegl1-mesa-dev
|
||||
LDFLAGS += -L../src
|
||||
LDLIBS = -lraylib -lm
|
||||
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo
|
||||
LDLIBS += -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo -framework QuartzCore
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
|
||||
@ -561,10 +561,12 @@ SHAPES = \
|
||||
shapes/shapes_dashed_line \
|
||||
shapes/shapes_digital_clock \
|
||||
shapes/shapes_double_pendulum \
|
||||
shapes/shapes_drag_puzzle \
|
||||
shapes/shapes_easings_ball \
|
||||
shapes/shapes_easings_box \
|
||||
shapes/shapes_easings_rectangles \
|
||||
shapes/shapes_easings_testbed \
|
||||
shapes/shapes_ellipse_collision \
|
||||
shapes/shapes_following_eyes \
|
||||
shapes/shapes_hilbert_curve \
|
||||
shapes/shapes_kaleidoscope \
|
||||
@ -575,8 +577,11 @@ SHAPES = \
|
||||
shapes/shapes_math_angle_rotation \
|
||||
shapes/shapes_math_sine_cosine \
|
||||
shapes/shapes_mouse_trail \
|
||||
shapes/shapes_outlines_testbed \
|
||||
shapes/shapes_outlines_thickness \
|
||||
shapes/shapes_penrose_tile \
|
||||
shapes/shapes_pie_chart \
|
||||
shapes/shapes_polygon_lines \
|
||||
shapes/shapes_rectangle_advanced \
|
||||
shapes/shapes_rectangle_scaling \
|
||||
shapes/shapes_recursive_tree \
|
||||
@ -614,6 +619,7 @@ TEXTURES = \
|
||||
textures/textures_npatch_drawing \
|
||||
textures/textures_particles_blending \
|
||||
textures/textures_polygon_drawing \
|
||||
textures/textures_portal_window \
|
||||
textures/textures_raw_data \
|
||||
textures/textures_screen_buffer \
|
||||
textures/textures_sprite_animation \
|
||||
@ -665,8 +671,10 @@ MODELS = \
|
||||
models/models_loading_vox \
|
||||
models/models_mesh_generation \
|
||||
models/models_mesh_picking \
|
||||
models/models_mesh_uv_painting \
|
||||
models/models_orthographic_projection \
|
||||
models/models_point_rendering \
|
||||
models/models_procedural_decals \
|
||||
models/models_rlgl_solar_system \
|
||||
models/models_rotating_cube \
|
||||
models/models_skybox_rendering \
|
||||
@ -692,6 +700,7 @@ SHADERS = \
|
||||
shaders/shaders_hybrid_rendering \
|
||||
shaders/shaders_julia_set \
|
||||
shaders/shaders_lightmap_rendering \
|
||||
shaders/shaders_lights_bloom \
|
||||
shaders/shaders_mandelbrot_set \
|
||||
shaders/shaders_mesh_instancing \
|
||||
shaders/shaders_model_shader \
|
||||
@ -713,6 +722,7 @@ SHADERS = \
|
||||
shaders/shaders_vertex_displacement
|
||||
|
||||
AUDIO = \
|
||||
audio/audio_amp_envelope \
|
||||
audio/audio_mixed_processor \
|
||||
audio/audio_module_playing \
|
||||
audio/audio_music_stream \
|
||||
@ -921,6 +931,9 @@ shapes/shapes_digital_clock: shapes/shapes_digital_clock.c
|
||||
shapes/shapes_double_pendulum: shapes/shapes_double_pendulum.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_drag_puzzle: shapes/shapes_drag_puzzle.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_easings_ball: shapes/shapes_easings_ball.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
@ -933,6 +946,9 @@ shapes/shapes_easings_rectangles: shapes/shapes_easings_rectangles.c
|
||||
shapes/shapes_easings_testbed: shapes/shapes_easings_testbed.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_ellipse_collision: shapes/shapes_ellipse_collision.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_following_eyes: shapes/shapes_following_eyes.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
@ -963,12 +979,21 @@ shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c
|
||||
shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_outlines_testbed: shapes/shapes_outlines_testbed.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_outlines_thickness: shapes/shapes_outlines_thickness.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_penrose_tile: shapes/shapes_penrose_tile.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_pie_chart: shapes/shapes_pie_chart.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_polygon_lines: shapes/shapes_polygon_lines.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
@ -1098,6 +1123,9 @@ textures/textures_polygon_drawing: textures/textures_polygon_drawing.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--preload-file textures/resources/cat.png@resources/cat.png
|
||||
|
||||
textures/textures_portal_window: textures/textures_portal_window.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
textures/textures_raw_data: textures/textures_raw_data.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--preload-file textures/resources/fudesumi.raw@resources/fudesumi.raw
|
||||
@ -1317,12 +1345,18 @@ models/models_mesh_picking: models/models_mesh_picking.c
|
||||
--preload-file models/resources/models/obj/turret.obj@resources/models/obj/turret.obj \
|
||||
--preload-file models/resources/models/obj/turret_diffuse.png@resources/models/obj/turret_diffuse.png
|
||||
|
||||
models/models_mesh_uv_painting: models/models_mesh_uv_painting.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
models/models_orthographic_projection: models/models_orthographic_projection.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
models/models_point_rendering: models/models_point_rendering.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
models/models_procedural_decals: models/models_procedural_decals.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
models/models_rlgl_solar_system: models/models_rlgl_solar_system.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
@ -1460,6 +1494,12 @@ shaders/shaders_lightmap_rendering: shaders/shaders_lightmap_rendering.c
|
||||
--preload-file shaders/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png \
|
||||
--preload-file shaders/resources/spark_flame.png@resources/spark_flame.png
|
||||
|
||||
shaders/shaders_lights_bloom: shaders/shaders_lights_bloom.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--preload-file shaders/resources/shaders/glsl100/lights_bloom.vs@resources/shaders/glsl100/lights_bloom.vs \
|
||||
--preload-file shaders/resources/shaders/glsl100/lights_bloom.fs@resources/shaders/glsl100/lights_bloom.fs \
|
||||
--preload-file shaders/resources/shaders/glsl100/lights_bloom_post.fs@resources/shaders/glsl100/lights_bloom_post.fs
|
||||
|
||||
shaders/shaders_mandelbrot_set: shaders/shaders_mandelbrot_set.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--preload-file shaders/resources/shaders/glsl100/mandelbrot_set.fs@resources/shaders/glsl100/mandelbrot_set.fs
|
||||
@ -1567,6 +1607,9 @@ shaders/shaders_vertex_displacement: shaders/shaders_vertex_displacement.c
|
||||
--preload-file shaders/resources/shaders/glsl100/vertex_displacement.fs@resources/shaders/glsl100/vertex_displacement.fs
|
||||
|
||||
# Compile AUDIO examples
|
||||
audio/audio_amp_envelope: audio/audio_amp_envelope.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
|
||||
audio/audio_mixed_processor: audio/audio_mixed_processor.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--preload-file audio/resources/country.mp3@resources/country.mp3 \
|
||||
|
||||
@ -13,11 +13,13 @@ The examples assume you have already built the `raylib` library in `../src`.
|
||||
The [Zig](https://ziglang.org/) toolchain can compile `C` and `C++` in addition to `Zig`.
|
||||
You may find it easier to use than other toolchains, especially when it comes to cross-compiling.
|
||||
|
||||
- `zig build` to compile all examples
|
||||
Run the following commands from the repository root:
|
||||
|
||||
- `zig build examples` to compile all examples
|
||||
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
|
||||
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
|
||||
|
||||
## EXAMPLES COLLECTION [TOTAL: 212]
|
||||
## EXAMPLES COLLECTION [TOTAL: 222]
|
||||
|
||||
### category: core [49]
|
||||
|
||||
@ -75,7 +77,7 @@ Examples using raylib [core](../src/rcore.c) module platform functionality: wind
|
||||
| [core_keyboard_testbed](core/core_keyboard_testbed.c) | <img src="core/core_keyboard_testbed.png" alt="core_keyboard_testbed" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [core_window_web](core/core_window_web.c) | <img src="core/core_window_web.png" alt="core_window_web" width="80"> | ⭐☆☆☆ | 1.3 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
|
||||
### category: shapes [40]
|
||||
### category: shapes [45]
|
||||
|
||||
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
|
||||
|
||||
@ -121,8 +123,13 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
|
||||
| [shapes_penrose_tile](shapes/shapes_penrose_tile.c) | <img src="shapes/shapes_penrose_tile.png" alt="shapes_penrose_tile" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
|
||||
| [shapes_hilbert_curve](shapes/shapes_hilbert_curve.c) | <img src="shapes/shapes_hilbert_curve.png" alt="shapes_hilbert_curve" width="80"> | ⭐⭐⭐☆ | 5.6 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
|
||||
| [shapes_easings_testbed](shapes/shapes_easings_testbed.c) | <img src="shapes/shapes_easings_testbed.png" alt="shapes_easings_testbed" width="80"> | ⭐⭐⭐☆ | 2.5 | 2.5 | [Juan Miguel López](https://github.com/flashback-fx) |
|
||||
| [shapes_drag_puzzle](shapes/shapes_drag_puzzle.c) | <img src="shapes/shapes_drag_puzzle.png" alt="shapes_drag_puzzle" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Gabriel Piangers](https://github.com/gabriel-piangers) |
|
||||
| [shapes_ellipse_collision](shapes/shapes_ellipse_collision.c) | <img src="shapes/shapes_ellipse_collision.png" alt="shapes_ellipse_collision" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Ziya](https://github.com/Monjaris) |
|
||||
| [shapes_outlines_testbed](shapes/shapes_outlines_testbed.c) | <img src="shapes/shapes_outlines_testbed.png" alt="shapes_outlines_testbed" width="80"> | ⭐⭐⭐☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
|
||||
| [shapes_outlines_thickness](shapes/shapes_outlines_thickness.c) | <img src="shapes/shapes_outlines_thickness.png" alt="shapes_outlines_thickness" width="80"> | ⭐☆☆☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
|
||||
| [shapes_polygon_lines](shapes/shapes_polygon_lines.c) | <img src="shapes/shapes_polygon_lines.png" alt="shapes_polygon_lines" width="80"> | ⭐⭐☆☆ | 6.1 | 6.1 | [Matthew Roush](https://github.com/MatthewRoush) |
|
||||
|
||||
### category: textures [32]
|
||||
### category: textures [33]
|
||||
|
||||
Examples using raylib textures functionality, including image/textures loading/generation and drawing, provided by raylib [textures](../src/rtextures.c) module.
|
||||
|
||||
@ -146,7 +153,7 @@ Examples using raylib textures functionality, including image/textures loading/g
|
||||
| [textures_sprite_button](textures/textures_sprite_button.c) | <img src="textures/textures_sprite_button.png" alt="textures_sprite_button" width="80"> | ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_sprite_explosion](textures/textures_sprite_explosion.c) | <img src="textures/textures_sprite_explosion.png" alt="textures_sprite_explosion" width="80"> | ⭐⭐☆☆ | 2.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_bunnymark](textures/textures_bunnymark.c) | <img src="textures/textures_bunnymark.png" alt="textures_bunnymark" width="80"> | ⭐⭐⭐☆ | 1.6 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐⭐⭐☆ | 3.0 | 3.0 | [Chris Dill](https://github.com/MysteriousSpace) |
|
||||
| [textures_mouse_painting](textures/textures_mouse_painting.c) | <img src="textures/textures_mouse_painting.png" alt="textures_mouse_painting" width="80"> | ⭐⭐⭐☆ | 3.0 | 6.0 | [Chris Dill](https://github.com/MysteriousSpace) |
|
||||
| [textures_blend_modes](textures/textures_blend_modes.c) | <img src="textures/textures_blend_modes.png" alt="textures_blend_modes" width="80"> | ⭐☆☆☆ | 3.5 | 3.5 | [Karlo Licudine](https://github.com/accidentalrebel) |
|
||||
| [textures_tiled_drawing](textures/textures_tiled_drawing.c) | <img src="textures/textures_tiled_drawing.png" alt="textures_tiled_drawing" width="80"> | ⭐⭐⭐☆ | 3.0 | 4.2 | [Vlad Adrian](https://github.com/demizdor) |
|
||||
| [textures_polygon_drawing](textures/textures_polygon_drawing.c) | <img src="textures/textures_polygon_drawing.png" alt="textures_polygon_drawing" width="80"> | ⭐☆☆☆ | 3.7 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) |
|
||||
@ -160,6 +167,7 @@ Examples using raylib textures functionality, including image/textures loading/g
|
||||
| [textures_sprite_stacking](textures/textures_sprite_stacking.c) | <img src="textures/textures_sprite_stacking.png" alt="textures_sprite_stacking" width="80"> | ⭐⭐☆☆ | 6.0 | 6.0 | [Robin](https://github.com/RobinsAviary) |
|
||||
| [textures_cellular_automata](textures/textures_cellular_automata.c) | <img src="textures/textures_cellular_automata.png" alt="textures_cellular_automata" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) |
|
||||
| [textures_framebuffer_rendering](textures/textures_framebuffer_rendering.c) | <img src="textures/textures_framebuffer_rendering.png" alt="textures_framebuffer_rendering" width="80"> | ⭐⭐☆☆ | 5.6 | 5.6 | [Jack Boakes](https://github.com/jackboakes) |
|
||||
| [textures_portal_window](textures/textures_portal_window.c) | <img src="textures/textures_portal_window.png" alt="textures_portal_window" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
|
||||
|
||||
### category: text [16]
|
||||
|
||||
@ -184,7 +192,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat
|
||||
| [text_words_alignment](text/text_words_alignment.c) | <img src="text/text_words_alignment.png" alt="text_words_alignment" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [JP Mortiboys](https://github.com/themushroompirates) |
|
||||
| [text_strings_management](text/text_strings_management.c) | <img src="text/text_strings_management.png" alt="text_strings_management" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [David Buzatto](https://github.com/davidbuzatto) |
|
||||
|
||||
### category: models [30]
|
||||
### category: models [32]
|
||||
|
||||
Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module.
|
||||
|
||||
@ -220,8 +228,10 @@ Examples using raylib models functionality, including models loading/generation
|
||||
| [models_animation_blend_custom](models/models_animation_blend_custom.c) | <img src="models/models_animation_blend_custom.png" alt="models_animation_blend_custom" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [dmitrii-brand](https://github.com/dmitrii-brand) |
|
||||
| [models_animation_blending](models/models_animation_blending.c) | <img src="models/models_animation_blending.png" alt="models_animation_blending" width="80"> | ⭐⭐⭐⭐️ | 5.5 | 6.0 | [Kirandeep](https://github.com/Kirandeep-Singh-Khehra) |
|
||||
| [models_animation_timing](models/models_animation_timing.c) | <img src="models/models_animation_timing.png" alt="models_animation_timing" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [models_mesh_uv_painting](models/models_mesh_uv_painting.c) | <img src="models/models_mesh_uv_painting.png" alt="models_mesh_uv_painting" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
|
||||
| [models_procedural_decals](models/models_procedural_decals.c) | <img src="models/models_procedural_decals.png" alt="models_procedural_decals" width="80"> | ⭐⭐⭐⭐️ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
|
||||
|
||||
### category: shaders [35]
|
||||
### category: shaders [36]
|
||||
|
||||
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.h) module.
|
||||
|
||||
@ -262,8 +272,9 @@ Examples using raylib shaders functionality, including shaders loading, paramete
|
||||
| [shaders_game_of_life](shaders/shaders_game_of_life.c) | <img src="shaders/shaders_game_of_life.png" alt="shaders_game_of_life" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Jordi Santonja](https://github.com/JordSant) |
|
||||
| [shaders_rlgl_compute](shaders/shaders_rlgl_compute.c) | <img src="shaders/shaders_rlgl_compute.png" alt="shaders_rlgl_compute" width="80"> | ⭐⭐⭐⭐️ | 4.0 | 4.0 | [Teddy Astie](https://github.com/tsnake41) |
|
||||
| [shaders_cel_shading](shaders/shaders_cel_shading.c) | <img src="shaders/shaders_cel_shading.png" alt="shaders_cel_shading" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Gleb A](https://github.com/ggrizzly) |
|
||||
| [shaders_lights_bloom](shaders/shaders_lights_bloom.c) | <img src="shaders/shaders_lights_bloom.png" alt="shaders_lights_bloom" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [PanicTitan](https://github.com/PanicTitan) |
|
||||
|
||||
### category: audio [10]
|
||||
### category: audio [11]
|
||||
|
||||
Examples using raylib audio functionality, including sound/music loading and playing. This functionality is provided by raylib [raudio](../src/raudio.c) module. Note this module can be used standalone independently of raylib.
|
||||
|
||||
@ -276,9 +287,10 @@ Examples using raylib audio functionality, including sound/music loading and pla
|
||||
| [audio_mixed_processor](audio/audio_mixed_processor.c) | <img src="audio/audio_mixed_processor.png" alt="audio_mixed_processor" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [hkc](https://github.com/hatkidchan) |
|
||||
| [audio_stream_effects](audio/audio_stream_effects.c) | <img src="audio/audio_stream_effects.png" alt="audio_stream_effects" width="80"> | ⭐⭐⭐⭐️ | 4.2 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
|
||||
| [audio_sound_multi](audio/audio_sound_multi.c) | <img src="audio/audio_sound_multi.png" alt="audio_sound_multi" width="80"> | ⭐⭐☆☆ | 5.0 | 5.0 | [Jeffery Myers](https://github.com/JeffM2501) |
|
||||
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 5.5 | [Le Juez Victor](https://github.com/Bigfoot71) |
|
||||
| [audio_sound_positioning](audio/audio_sound_positioning.c) | <img src="audio/audio_sound_positioning.png" alt="audio_sound_positioning" width="80"> | ⭐⭐☆☆ | 5.5 | 6.0 | [Le Juez Victor](https://github.com/Bigfoot71) |
|
||||
| [audio_spectrum_visualizer](audio/audio_spectrum_visualizer.c) | <img src="audio/audio_spectrum_visualizer.png" alt="audio_spectrum_visualizer" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [IANN](https://github.com/meisei4) |
|
||||
| [audio_stream_callback](audio/audio_stream_callback.c) | <img src="audio/audio_stream_callback.png" alt="audio_stream_callback" width="80"> | ⭐⭐⭐☆ | 6.0 | 6.0 | [Dan Hoang](https://github.com/dan-hoang) |
|
||||
| [audio_amp_envelope](audio/audio_amp_envelope.c) | <img src="audio/audio_amp_envelope.png" alt="audio_amp_envelope" width="80"> | ⭐☆☆☆ | 6.0 | 6.0 | [Arbinda Rizki Muhammad](https://github.com/arbipink) |
|
||||
|
||||
Some example missing? As always, contributions are welcome, feel free to send new examples!
|
||||
Here is an [examples template](examples_template.c) with instructions to start with!
|
||||
|
||||
@ -113,6 +113,7 @@ int main(void)
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadMusicStream(music); // Unload music stream buffers from RAM
|
||||
UnloadSound(sound);
|
||||
|
||||
DetachAudioMixedProcessor(ProcessAudio); // Disconnect audio processor
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ int main(void)
|
||||
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||
{
|
||||
int wavelength = SAMPLE_RATE/sineFrequency;
|
||||
buffer[i] = sin(2*PI*sineIndex/wavelength);
|
||||
buffer[i] = sinf(2*PI*sineIndex/wavelength);
|
||||
sineIndex++;
|
||||
|
||||
if (sineIndex >= wavelength)
|
||||
@ -116,8 +116,8 @@ int main(void)
|
||||
DrawText("Up/down to change frequency", 10, 10, 20, DARKGRAY);
|
||||
DrawText("Left/right to pan", 10, 30, 20, DARKGRAY);
|
||||
|
||||
int windowStart = (GetTime() - sineStartTime)*SAMPLE_RATE;
|
||||
int windowSize = 0.1f*SAMPLE_RATE;
|
||||
int windowStart = (int)((GetTime() - sineStartTime)*SAMPLE_RATE);
|
||||
int windowSize = SAMPLE_RATE/10;
|
||||
int wavelength = SAMPLE_RATE/sineFrequency;
|
||||
|
||||
// Draw a sine wave with the same frequency as the one being sent to the audio stream
|
||||
@ -125,8 +125,8 @@ int main(void)
|
||||
{
|
||||
int t0 = windowStart + i*windowSize/screenWidth;
|
||||
int t1 = windowStart + (i + 1)*windowSize/screenWidth;
|
||||
Vector2 startPos = { i, 250 + 50*sin(2*PI*t0/wavelength) };
|
||||
Vector2 endPos = { i + 1, 250 + 50*sin(2*PI*t1/wavelength) };
|
||||
Vector2 startPos = { (float)i, 250 + 50*sinf(2*PI*t0/wavelength) };
|
||||
Vector2 endPos = { (float)i + 1, 250 + 50*sinf(2*PI*t1/wavelength) };
|
||||
DrawLineV(startPos, endPos, RED);
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 5.5
|
||||
* Example originally created with raylib 5.5, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Le Juez Victor (@Bigfoot71) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
@ -116,14 +116,14 @@ static void SetSoundPosition(Camera listener, Sound sound, Vector3 position, flo
|
||||
// Calculate normalized vectors for spatial positioning
|
||||
Vector3 normalizedDirection = Vector3Normalize(direction);
|
||||
Vector3 forward = Vector3Normalize(Vector3Subtract(listener.target, listener.position));
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(listener.up, forward));
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(forward, listener.up));
|
||||
|
||||
// Reduce volume for sounds behind the listener
|
||||
float dotProduct = Vector3DotProduct(forward, normalizedDirection);
|
||||
if (dotProduct < 0.0f) attenuation *= (1.0f + dotProduct*0.5f);
|
||||
|
||||
// Set stereo panning based on sound position relative to listener
|
||||
float pan = 0.5f + 0.5f*Vector3DotProduct(normalizedDirection, right);
|
||||
float pan = Vector3DotProduct(normalizedDirection, right);
|
||||
|
||||
// Apply final sound properties
|
||||
SetSoundVolume(sound, attenuation);
|
||||
|
||||
@ -133,8 +133,8 @@ int main(void)
|
||||
// Draw the last 10 ms of uploaded audio
|
||||
for (int i = 0; i < screenWidth; i++)
|
||||
{
|
||||
Vector2 startPos = { i, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + i*SAMPLE_RATE/100/screenWidth] };
|
||||
Vector2 endPos = { i + 1, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + (i + 1)*SAMPLE_RATE/100/screenWidth] };
|
||||
Vector2 startPos = {(float)i, 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + i*SAMPLE_RATE/100/screenWidth] };
|
||||
Vector2 endPos = { (float)(i + 1), 250 - 50*buffer[SAMPLE_RATE - SAMPLE_RATE/100 + (i + 1)*SAMPLE_RATE/100/screenWidth] };
|
||||
DrawLineV(startPos, endPos, RED);
|
||||
}
|
||||
|
||||
@ -161,9 +161,9 @@ static void SineCallback(void *framesOut, unsigned int frameCount)
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the sine wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
for (unsigned int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = sin(2*PI*waveIndex/wavelength);
|
||||
((float *)framesOut)[i] = sinf(2*PI*waveIndex/wavelength);
|
||||
|
||||
waveIndex++;
|
||||
|
||||
@ -175,8 +175,8 @@ static void SineCallback(void *framesOut, unsigned int frameCount)
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
}
|
||||
|
||||
static void SquareCallback(void *framesOut, unsigned int frameCount)
|
||||
@ -184,9 +184,9 @@ static void SquareCallback(void *framesOut, unsigned int frameCount)
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the square wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
for (unsigned int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1 : -1;
|
||||
((float *)framesOut)[i] = (waveIndex < wavelength/2)? 1.0f : -1.0f;
|
||||
waveIndex++;
|
||||
|
||||
if (waveIndex >= wavelength)
|
||||
@ -197,8 +197,8 @@ static void SquareCallback(void *framesOut, unsigned int frameCount)
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
}
|
||||
|
||||
static void TriangleCallback(void *framesOut, unsigned int frameCount)
|
||||
@ -206,7 +206,7 @@ static void TriangleCallback(void *framesOut, unsigned int frameCount)
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the triangle wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
for (unsigned int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = (waveIndex < wavelength/2)? (-1 + 2.0f*waveIndex/(wavelength/2)) : (1 - 2.0f*(waveIndex - wavelength/2)/(wavelength/2));
|
||||
waveIndex++;
|
||||
@ -219,8 +219,8 @@ static void TriangleCallback(void *framesOut, unsigned int frameCount)
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
}
|
||||
|
||||
static void SawtoothCallback(void *framesOut, unsigned int frameCount)
|
||||
@ -228,7 +228,7 @@ static void SawtoothCallback(void *framesOut, unsigned int frameCount)
|
||||
int wavelength = SAMPLE_RATE/waveFrequency;
|
||||
|
||||
// Synthesize the sawtooth wave
|
||||
for (int i = 0; i < frameCount; i++)
|
||||
for (unsigned int i = 0; i < frameCount; i++)
|
||||
{
|
||||
((float *)framesOut)[i] = -1 + 2.0f*waveIndex/wavelength;
|
||||
waveIndex++;
|
||||
@ -241,6 +241,6 @@ static void SawtoothCallback(void *framesOut, unsigned int frameCount)
|
||||
}
|
||||
|
||||
// Save the synthesized samples for later drawing
|
||||
for (int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float *)framesOut)[i];
|
||||
for (unsigned int i = 0; i < SAMPLE_RATE - frameCount; i++) buffer[i] = buffer[i + frameCount];
|
||||
for (unsigned int i = 0; i < frameCount; i++) buffer[SAMPLE_RATE - frameCount + i] = ((float*)framesOut)[i];
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ int main(void)
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = (Vector2){ player.x + 20.0f, player.y + 20.0f };
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
|
||||
@ -65,8 +65,8 @@ int main(void)
|
||||
// Get the world point that is under the mouse
|
||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||
|
||||
// Set the offset to where the mouse is
|
||||
camera.offset = GetMousePosition();
|
||||
// Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
|
||||
camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
|
||||
|
||||
// Set the target to match, so that the camera maps the world space point
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
@ -86,8 +86,8 @@ int main(void)
|
||||
// Get the world point that is under the mouse
|
||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||
|
||||
// Set the offset to where the mouse is
|
||||
camera.offset = GetMousePosition();
|
||||
// Set the offset to where the mouse is, mouse is scaled to viewport space, but offset is in unscaled pixels
|
||||
camera.offset = Vector2Multiply(GetMousePosition(), GetWindowScaleDPI());
|
||||
|
||||
// Set the target to match, so that the camera maps the world space point
|
||||
// under the cursor to the screen space point under the cursor at any zoom
|
||||
|
||||
@ -75,7 +75,7 @@ int main(void)
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "raymath.h"
|
||||
|
||||
#define PLAYER_SIZE 40
|
||||
|
||||
@ -39,13 +40,13 @@ int main(void)
|
||||
|
||||
Camera2D camera1 = { 0 };
|
||||
camera1.target = (Vector2){ player1.x, player1.y };
|
||||
camera1.offset = (Vector2){ 200.0f, 200.0f };
|
||||
camera1.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
|
||||
camera1.rotation = 0.0f;
|
||||
camera1.zoom = 1.0f;
|
||||
|
||||
Camera2D camera2 = { 0 };
|
||||
camera2.target = (Vector2){ player2.x, player2.y };
|
||||
camera2.offset = (Vector2){ 200.0f, 200.0f };
|
||||
camera2.offset = Vector2Multiply((Vector2){ 200.0f, 200.0f }, GetWindowScaleDPI());
|
||||
camera2.rotation = 0.0f;
|
||||
camera2.zoom = 1.0f;
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ int main(void)
|
||||
// Define camera
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
@ -117,7 +117,7 @@ int main(void)
|
||||
player.canJump = false;
|
||||
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
}
|
||||
@ -169,7 +169,7 @@ int main(void)
|
||||
player.canJump = false;
|
||||
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
}
|
||||
@ -205,7 +205,7 @@ int main(void)
|
||||
// Update camera
|
||||
//----------------------------------------------------------------------------------
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
|
||||
|
||||
// WARNING: On event replay, mouse-wheel internal value is set
|
||||
@ -267,7 +267,7 @@ int main(void)
|
||||
player.canJump = false;
|
||||
|
||||
camera.target = player.position;
|
||||
camera.offset = (Vector2){ screenWidth/2.0f, screenHeight/2.0f };
|
||||
camera.offset = (Vector2){ GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
camera.rotation = 0.0f;
|
||||
camera.zoom = 1.0f;
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ int main(void)
|
||||
if (currentFps <= 0) fpsText = TextFormat("FPS: unlimited (%i)", GetFPS());
|
||||
else fpsText = TextFormat("FPS: %i (target: %i)", GetFPS(), currentFps);
|
||||
DrawText(fpsText, 10, 10, 20, DARKGRAY);
|
||||
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()), 10, 30, 20, DARKGRAY);
|
||||
DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()*1000.0f), 10, 30, 20, DARKGRAY);
|
||||
DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, DARKGRAY);
|
||||
|
||||
// Draw the text above the circles
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
#define MAX_FILEPATH_SIZE 1024
|
||||
#define FILE_FILTER "DIRS*;.png;.c"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
@ -41,7 +42,7 @@ int main(void)
|
||||
// NOTE: LoadDirectoryFiles() loads files and directories by default,
|
||||
// use LoadDirectoryFilesEx() for custom filters and recursive directories loading
|
||||
//FilePathList files = LoadDirectoryFiles(directory);
|
||||
FilePathList files = LoadDirectoryFilesEx(directory, ".png;.c", false);
|
||||
FilePathList files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
|
||||
|
||||
int btnBackPressed = false;
|
||||
|
||||
@ -61,7 +62,22 @@ int main(void)
|
||||
{
|
||||
TextCopy(directory, GetPrevDirectoryPath(directory));
|
||||
UnloadDirectoryFiles(files);
|
||||
files = LoadDirectoryFiles(directory);
|
||||
files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
|
||||
|
||||
listScrollIndex = 0;
|
||||
listItemActive = -1;
|
||||
listItemFocused = -1;
|
||||
}
|
||||
|
||||
if ((listItemActive >= 0) && (listItemActive < (int)files.count) && DirectoryExists(files.paths[listItemActive]))
|
||||
{
|
||||
TextCopy(directory, files.paths[listItemActive]);
|
||||
UnloadDirectoryFiles(files);
|
||||
files = LoadDirectoryFilesEx(directory, FILE_FILTER, false);
|
||||
|
||||
listScrollIndex = 0;
|
||||
listItemActive = -1;
|
||||
listItemFocused = -1;
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ int main(void)
|
||||
DrawCircleV(GetMousePosition(), 20, MAROON);
|
||||
DrawRectangleRec((Rectangle) { mousePos.x - 25, mousePos.y, 50, 2 }, BLACK);
|
||||
DrawRectangleRec((Rectangle) { mousePos.x, mousePos.y - 25, 2, 50 }, BLACK);
|
||||
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), mousePos.x - 44,
|
||||
DrawText(TextFormat("[%i,%i]", GetMouseX(), GetMouseY()), (int)mousePos.x - 44,
|
||||
(mousePos.y > GetScreenHeight() - 60)? (int)mousePos.y - 46 : (int)mousePos.y + 30, 20, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
@ -97,9 +97,6 @@ int main(void)
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// TODO: Unload all loaded resources at this point
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -94,6 +94,7 @@ int main(void)
|
||||
|
||||
// De-Initialization
|
||||
//---------------------------------------------------------
|
||||
UnloadRenderTexture(target);
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ int main(void)
|
||||
|
||||
// The target's height is flipped (in the source Rectangle), due to OpenGL reasons
|
||||
Rectangle sourceRec = { 0.0f, 0.0f, (float)target.texture.width, -(float)target.texture.height };
|
||||
Rectangle destRec = { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
|
||||
Rectangle destRec = { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f };
|
||||
|
||||
Vector2 origin = { 0.0f, 0.0f };
|
||||
|
||||
@ -61,6 +61,9 @@ int main(void)
|
||||
float cameraX = 0.0f;
|
||||
float cameraY = 0.0f;
|
||||
|
||||
bool smoothOn = true;
|
||||
bool overscan = false;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
@ -86,6 +89,18 @@ int main(void)
|
||||
worldSpaceCamera.target.y = truncf(screenSpaceCamera.target.y);
|
||||
screenSpaceCamera.target.y -= worldSpaceCamera.target.y;
|
||||
screenSpaceCamera.target.y *= virtualRatio;
|
||||
|
||||
if (IsKeyPressed(KEY_S)) smoothOn = !smoothOn;
|
||||
if (IsKeyPressed(KEY_O)) overscan = !overscan;
|
||||
|
||||
if (overscan)
|
||||
{
|
||||
destRec = (Rectangle) { -virtualRatio, -virtualRatio, screenWidth + (virtualRatio*2), screenHeight + (virtualRatio*2) };
|
||||
}
|
||||
else
|
||||
{
|
||||
destRec = (Rectangle) { (screenWidth - screenWidth/1.25f)/2.0f, (screenHeight - screenHeight/1.25f)/2.0f, screenWidth/1.25f, screenHeight/1.25f };
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
@ -101,14 +116,23 @@ int main(void)
|
||||
EndTextureMode();
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(RED);
|
||||
ClearBackground(LIGHTGRAY);
|
||||
|
||||
BeginMode2D(screenSpaceCamera);
|
||||
if (smoothOn)
|
||||
{
|
||||
BeginMode2D(screenSpaceCamera);
|
||||
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
|
||||
EndMode2D();
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawTexturePro(target.texture, sourceRec, destRec, origin, 0.0f, WHITE);
|
||||
EndMode2D();
|
||||
}
|
||||
|
||||
DrawText(TextFormat("Screen resolution: %ix%i", screenWidth, screenHeight), 10, 10, 20, DARKBLUE);
|
||||
DrawText(TextFormat("World resolution: %ix%i", virtualScreenWidth, virtualScreenHeight), 10, 40, 20, DARKGREEN);
|
||||
DrawText(TextFormat("Smooth: %s", (smoothOn ? "ON" : "OFF")), 10, screenHeight - 60, 20, RED);
|
||||
DrawText(TextFormat("Overscan: %s", (overscan ? "ON" : "OFF")), 10, screenHeight - 30, 20, RED);
|
||||
DrawFPS(GetScreenWidth() - 95, 10);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -122,4 +146,4 @@ int main(void)
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 3.4 KiB |
1422
examples/example_resources.zon
Normal file
@ -9,7 +9,7 @@
|
||||
#
|
||||
# This list is used as the main reference by [rexm] tool for examples collection validation and management
|
||||
#
|
||||
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2025;"Ramon Santamaria";@raysan5
|
||||
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2026;"Ramon Santamaria";@raysan5
|
||||
core;core_delta_time;★☆☆☆;5.5;6.0;2025;2025;"Robin";@RobinsAviary
|
||||
core;core_input_keys;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
|
||||
core;core_input_mouse;★☆☆☆;1.0;5.5;2014;2025;"Ramon Santamaria";@raysan5
|
||||
@ -98,6 +98,11 @@ shapes;shapes_ball_physics;★★☆☆;6.0;6.0;2025;2025;"David Buzatto";@david
|
||||
shapes;shapes_penrose_tile;★★★★;5.5;6.0;2025;2025;"David Buzatto";@davidbuzatto
|
||||
shapes;shapes_hilbert_curve;★★★☆;5.6;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
|
||||
shapes;shapes_easings_testbed;★★★☆;2.5;2.5;2019;2025;"Juan Miguel López";@flashback-fx
|
||||
shapes;shapes_drag_puzzle;★☆☆☆;6.0;6.0;2026;2026;"Gabriel Piangers";@gabriel-piangers
|
||||
shapes;shapes_ellipse_collision;★★☆☆;5.5;5.5;2025;2025;"Ziya";@Monjaris
|
||||
shapes;shapes_outlines_testbed;★★★☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
|
||||
shapes;shapes_outlines_thickness;★☆☆☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
|
||||
shapes;shapes_polygon_lines;★★☆☆;6.1;6.1;2026;2026;"Matthew Roush";@MatthewRoush
|
||||
textures;textures_clipboard_image;★☆☆☆;6.0;6.0;2026;2026;"Maicon Santana";@maiconpintoabreu
|
||||
textures;textures_magnifying_glass;★★★☆;5.6;5.6;2026;2026;"Luke Vaughan";@badram
|
||||
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
|
||||
@ -116,7 +121,7 @@ textures;textures_sprite_animation;★★☆☆;1.3;1.3;2014;2025;"Ramon Santama
|
||||
textures;textures_sprite_button;★★☆☆;2.5;2.5;2019;2025;"Ramon Santamaria";@raysan5
|
||||
textures;textures_sprite_explosion;★★☆☆;2.5;3.5;2019;2025;"Ramon Santamaria";@raysan5
|
||||
textures;textures_bunnymark;★★★☆;1.6;2.5;2014;2025;"Ramon Santamaria";@raysan5
|
||||
textures;textures_mouse_painting;★★★☆;3.0;3.0;2019;2025;"Chris Dill";@MysteriousSpace
|
||||
textures;textures_mouse_painting;★★★☆;3.0;6.0;2019;2025;"Chris Dill";@MysteriousSpace
|
||||
textures;textures_blend_modes;★☆☆☆;3.5;3.5;2020;2025;"Karlo Licudine";@accidentalrebel
|
||||
textures;textures_tiled_drawing;★★★☆;3.0;4.2;2020;2025;"Vlad Adrian";@demizdor
|
||||
textures;textures_polygon_drawing;★☆☆☆;3.7;3.7;2021;2025;"Chris Camacho";@chriscamacho
|
||||
@ -130,6 +135,7 @@ textures;textures_textured_curve;★★★☆;4.5;4.5;2022;2025;"Jeffery Myers";
|
||||
textures;textures_sprite_stacking;★★☆☆;6.0;6.0;2025;2025;"Robin";@RobinsAviary
|
||||
textures;textures_cellular_automata;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant
|
||||
textures;textures_framebuffer_rendering;★★☆☆;5.6;5.6;2026;2026;"Jack Boakes";@jackboakes
|
||||
textures;textures_portal_window;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
|
||||
text;text_sprite_fonts;★☆☆☆;1.7;3.7;2017;2025;"Ramon Santamaria";@raysan5
|
||||
text;text_font_spritefont;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
|
||||
text;text_font_filters;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
|
||||
@ -176,6 +182,8 @@ models;models_directional_billboard;★★☆☆;6.0;6.0;2025;2025;"Robin";@Robi
|
||||
models;models_animation_blend_custom;★★★★;5.5;6.0;2026;2026;"dmitrii-brand";@dmitrii-brand
|
||||
models;models_animation_blending;★★★★;5.5;6.0;2024;2026;"Kirandeep";@Kirandeep-Singh-Khehra
|
||||
models;models_animation_timing;★★★☆;6.0;6.0;2026;2026;"Ramon Santamaria";@raysan5
|
||||
models;models_mesh_uv_painting;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
|
||||
models;models_procedural_decals;★★★★;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
|
||||
shaders;shaders_ascii_rendering;★★☆☆;5.5;6.0;2025;2025;"Maicon Santana";@maiconpintoabreu
|
||||
shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
|
||||
shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5
|
||||
@ -211,6 +219,7 @@ shaders;shaders_depth_rendering;★★★☆;6.0;6.0;2025;2025;"Luís Almeida";@
|
||||
shaders;shaders_game_of_life;★★★☆;6.0;6.0;2025;2025;"Jordi Santonja";@JordSant
|
||||
shaders;shaders_rlgl_compute;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake41
|
||||
shaders;shaders_cel_shading;★★★☆;6.0;6.0;2026;2026;"Gleb A";@ggrizzly
|
||||
shaders;shaders_lights_bloom;★★★☆;6.0;6.0;2025;2025;"PanicTitan";@PanicTitan
|
||||
audio;audio_module_playing;★☆☆☆;1.5;3.5;2016;2025;"Ramon Santamaria";@raysan5
|
||||
audio;audio_music_stream;★☆☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
|
||||
audio;audio_raw_stream;★★★☆;1.6;6.0;2015;2026;"Ramon Santamaria";@raysan5
|
||||
@ -218,6 +227,7 @@ audio;audio_sound_loading;★☆☆☆;1.1;3.5;2014;2025;"Ramon Santamaria";@ray
|
||||
audio;audio_mixed_processor;★★★★;4.2;4.2;2023;2025;"hkc";@hatkidchan
|
||||
audio;audio_stream_effects;★★★★;4.2;5.0;2022;2025;"Ramon Santamaria";@raysan5
|
||||
audio;audio_sound_multi;★★☆☆;5.0;5.0;2023;2025;"Jeffery Myers";@JeffM2501
|
||||
audio;audio_sound_positioning;★★☆☆;5.5;5.5;2025;2025;"Le Juez Victor";@Bigfoot71
|
||||
audio;audio_sound_positioning;★★☆☆;5.5;6.0;2025;2025;"Le Juez Victor";@Bigfoot71
|
||||
audio;audio_spectrum_visualizer;★★★☆;6.0;6.0;2025;2025;"IANN";@meisei4
|
||||
audio;audio_stream_callback;★★★☆;6.0;6.0;2026;2026;"Dan Hoang";@dan-hoang
|
||||
audio;audio_amp_envelope;★☆☆☆;6.0;6.0;2026;2026;"Arbinda Rizki Muhammad";@arbipink
|
||||
|
||||
@ -212,12 +212,12 @@ static void UpdateModelAnimationBones(Model *model, ModelAnimation *anim0, int f
|
||||
if (frame1 < 0) frame1 = 0;
|
||||
|
||||
// Get bone count (use minimum of all to be safe)
|
||||
int boneCount = model->skeleton.boneCount;
|
||||
unsigned int boneCount = model->skeleton.boneCount;
|
||||
if (anim0->boneCount < boneCount) boneCount = anim0->boneCount;
|
||||
if (anim1->boneCount < boneCount) boneCount = anim1->boneCount;
|
||||
|
||||
// Blend each bone
|
||||
for (int boneIndex = 0; boneIndex < boneCount; boneIndex++)
|
||||
for (unsigned int boneIndex = 0; boneIndex < boneCount; boneIndex++)
|
||||
{
|
||||
// Determine blend factor for this bone
|
||||
float boneBlendFactor = blend;
|
||||
|
||||
@ -53,13 +53,19 @@ int main(void)
|
||||
Model model = LoadModel("resources/models/gltf/robot.glb"); // Load character model
|
||||
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model world position
|
||||
|
||||
#if SUPPORT_GPU_SKINNING
|
||||
// WARNING: SUPPORT_GPU_SKINNING is required to be enabled at raylib compile time (disabled by default)
|
||||
// It will skip loading CPU required buffers to store animation updated data, so, both modes are exclusive
|
||||
|
||||
// Load skinning shader
|
||||
// WARNING: It requires SUPPORT_GPU_SKINNING enabled on raylib (disabled by default)
|
||||
// NOTE: It must be a valid shader, following raylib attribs/uniform conventions for GPU skinning
|
||||
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
|
||||
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
|
||||
|
||||
// Assign skinning shader to all materials shaders
|
||||
//for (int i = 0; i < model.materialCount; i++) model.materials[i].shader = skinningShader;
|
||||
// Skinning shader could be required to be assigned to all materials shaders, just to make
|
||||
// sure required uniforms are being updated for the mesh using that material (and shader)
|
||||
for (int i = 0; i < model.materialCount; i++) model.materials[i].shader = skinningShader;
|
||||
#endif
|
||||
|
||||
// Load model animations
|
||||
int animCount = 0;
|
||||
@ -108,7 +114,7 @@ int main(void)
|
||||
|
||||
if (IsKeyPressed(KEY_P)) animPause = !animPause;
|
||||
|
||||
if (!animPause)
|
||||
if (!animPause && (animCount > 0)) // Animations could fail to load
|
||||
{
|
||||
// Start transition from anim0[] to anim1[]
|
||||
if (IsKeyPressed(KEY_SPACE) && !animTransition)
|
||||
@ -244,21 +250,30 @@ int main(void)
|
||||
if (GuiDropdownBox((Rectangle){ GetScreenWidth() - 170.0f, 10, 160, 24 }, TextJoin(animNames, animCount, ";"),
|
||||
&animIndex1, dropdownEditMode1)) dropdownEditMode1 = !dropdownEditMode1;
|
||||
|
||||
// Draw playing timeline with keyframes for anim0[]
|
||||
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 60.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 0",
|
||||
TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount),
|
||||
&animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount);
|
||||
for (int i = 0; i < anims[animIndex0].keyframeCount; i++)
|
||||
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i),
|
||||
GetScreenHeight() - 60, 1, 20, BLUE);
|
||||
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize*2);
|
||||
GuiLabel((Rectangle){ 0, GetScreenHeight() - 100.0f, (float)GetScreenWidth(), 40 }, "PRESS SPACE to START BLENDING");
|
||||
GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetFont().baseSize);
|
||||
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
|
||||
|
||||
// Draw playing timeline with keyframes for anim1[]
|
||||
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 30.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 1",
|
||||
TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount),
|
||||
&animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount);
|
||||
for (int i = 0; i < anims[animIndex1].keyframeCount; i++)
|
||||
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i),
|
||||
GetScreenHeight() - 30, 1, 20, BLUE);
|
||||
if (animCount > 0)
|
||||
{
|
||||
// Draw playing timeline with keyframes for anim0[]
|
||||
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 60.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 0",
|
||||
TextFormat("FRAME: %.2f / %i", animFrameProgress0, anims[animIndex0].keyframeCount),
|
||||
&animFrameProgress0, 0.0f, (float)anims[animIndex0].keyframeCount);
|
||||
for (int i = 0; i < anims[animIndex0].keyframeCount; i++)
|
||||
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex0].keyframeCount)*(float)i),
|
||||
GetScreenHeight() - 60, 1, 20, BLUE);
|
||||
|
||||
// Draw playing timeline with keyframes for anim1[]
|
||||
GuiProgressBar((Rectangle){ 60, GetScreenHeight() - 30.0f, GetScreenWidth() - 180.0f, 20 }, "ANIM 1",
|
||||
TextFormat("FRAME: %.2f / %i", animFrameProgress1, anims[animIndex1].keyframeCount),
|
||||
&animFrameProgress1, 0.0f, (float)anims[animIndex1].keyframeCount);
|
||||
for (int i = 0; i < anims[animIndex1].keyframeCount; i++)
|
||||
DrawRectangle(60 + (int)(((float)(GetScreenWidth() - 180)/(float)anims[animIndex1].keyframeCount)*(float)i),
|
||||
GetScreenHeight() - 30, 1, 20, BLUE);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
EndDrawing();
|
||||
@ -269,7 +284,9 @@ int main(void)
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModelAnimations(anims, animCount); // Unload model animation
|
||||
UnloadModel(model); // Unload model and meshes/material
|
||||
#if SUPPORT_GPU_SKINNING
|
||||
UnloadShader(skinningShader); // Unload GPU skinning shader
|
||||
#endif
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
@ -52,12 +52,19 @@ int main(void)
|
||||
Model model = LoadModel("resources/models/gltf/greenman.glb"); // Load character model
|
||||
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
|
||||
|
||||
#if SUPPORT_GPU_SKINNING
|
||||
// WARNING: SUPPORT_GPU_SKINNING is required to be enabled at raylib compile time (disabled by default)
|
||||
// It will skip loading CPU required buffers to store animation updated data, so, both modes are exclusive
|
||||
|
||||
// Load skinning shader
|
||||
// WARNING: GPU skinning must be enabled in raylib with a compilation flag,
|
||||
// if not enabled, CPU skinning will be used instead
|
||||
// NOTE: It must be a valid shader, following raylib attribs/uniform conventions for GPU skinning
|
||||
Shader skinningShader = LoadShader(TextFormat("resources/shaders/glsl%i/skinning.vs", GLSL_VERSION),
|
||||
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
|
||||
model.materials[1].shader = skinningShader;
|
||||
TextFormat("resources/shaders/glsl%i/skinning.fs", GLSL_VERSION));
|
||||
|
||||
// Skinning shader could be required to be assigned to all materials shaders, just to make
|
||||
// sure required uniforms are being updated for the mesh using that material (and shader)
|
||||
model.materials[1].shader = skinningShader; // Just assigning to materials[1] for this model
|
||||
#endif
|
||||
|
||||
// Load gltf model animations
|
||||
int animCount = 0;
|
||||
@ -111,7 +118,9 @@ int main(void)
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModelAnimations(anims, animCount); // Unload model animation
|
||||
UnloadModel(model); // Unload model and meshes/material
|
||||
#if SUPPORT_GPU_SKINNING
|
||||
UnloadShader(skinningShader); // Unload GPU skinning shader
|
||||
#endif
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
@ -77,7 +77,7 @@ int main(void)
|
||||
{
|
||||
// Cast a ray from the screen center (where crosshair would be)
|
||||
Vector2 screenCenter = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
|
||||
Ray ray = GetMouseRay(screenCenter, camera);
|
||||
Ray ray = GetScreenToWorldRay(screenCenter, camera);
|
||||
|
||||
// Check ray collision with all voxels
|
||||
float closestDistance = 99999.0f;
|
||||
@ -103,7 +103,7 @@ int main(void)
|
||||
if (collision.hit && (collision.distance < closestDistance))
|
||||
{
|
||||
closestDistance = collision.distance;
|
||||
closestVoxelPosition = (Vector3){ x, y, z };
|
||||
closestVoxelPosition = (Vector3){ (float)x, (float)y, (float)z };
|
||||
voxelFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ int main(void)
|
||||
int boneSocketIndex[BONE_SOCKETS] = { -1, -1, -1 };
|
||||
|
||||
// Search bones for sockets
|
||||
for (int i = 0; i < characterModel.skeleton.boneCount; i++)
|
||||
for (unsigned int i = 0; i < characterModel.skeleton.boneCount; i++)
|
||||
{
|
||||
if (TextIsEqual(characterModel.skeleton.bones[i].name, "socket_hat"))
|
||||
{
|
||||
|
||||
@ -249,7 +249,7 @@ int main(void)
|
||||
DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY);
|
||||
|
||||
// UI elements
|
||||
if (GuiButton((Rectangle){ 10, screenHeight - 1000.f, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
|
||||
if (GuiButton((Rectangle){ 10, screenHeight - 100.0f, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel;
|
||||
|
||||
if (GuiButton((Rectangle){ 10 + 110, screenHeight - 100.0f, 100, 60 }, "Clear Decals"))
|
||||
{
|
||||
@ -267,6 +267,7 @@ int main(void)
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModel(model);
|
||||
UnloadModel(placementCube);
|
||||
UnloadTexture(modelTexture);
|
||||
|
||||
// Unload decal models
|
||||
|
||||
@ -106,4 +106,3 @@ int main(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include <math.h> // Required for: fmaxf(), fminf()
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
@ -53,6 +55,7 @@ int main(void)
|
||||
// Animation playing variables
|
||||
unsigned int animIndex = 0; // Current animation playing
|
||||
float animCurrentFrame = 0.0f; // Current animation frame (supporting interpolated frames)
|
||||
float animSpeed = 1.0f; // How fast the animation plays
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -64,10 +67,23 @@ int main(void)
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera, CAMERA_ORBITAL);
|
||||
|
||||
// Play animation when spacebar is held down
|
||||
animCurrentFrame += 1.0f;
|
||||
UpdateModelAnimation(model, anims[0], animCurrentFrame);
|
||||
if (animCurrentFrame >= anims[0].keyframeCount) animCurrentFrame = 0;
|
||||
if (IsKeyPressed(KEY_RIGHT))
|
||||
{
|
||||
animIndex = (animIndex == animCount - 1)? 0 : animIndex + 1;
|
||||
animCurrentFrame = 0.0f;
|
||||
}
|
||||
if (IsKeyPressed(KEY_LEFT))
|
||||
{
|
||||
animIndex = (animIndex == 0)? animCount - 1 : animIndex - 1;
|
||||
animCurrentFrame = 0.0f;
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_UP)) animSpeed = fminf(5.0f, animSpeed + 0.1f);
|
||||
if (IsKeyPressed(KEY_DOWN)) animSpeed = fmaxf(0.0f, animSpeed - 0.1f);
|
||||
|
||||
animCurrentFrame += animSpeed;
|
||||
UpdateModelAnimation(model, anims[animIndex], animCurrentFrame);
|
||||
if (animCurrentFrame >= anims[animIndex].keyframeCount) animCurrentFrame = 0;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
@ -85,6 +101,9 @@ int main(void)
|
||||
EndMode3D();
|
||||
|
||||
DrawText(TextFormat("Current animation: %s", anims[animIndex].name), 10, 10, 20, MAROON);
|
||||
DrawText(TextFormat("Animation speed: %.2f", animSpeed), 10, 40, 20, MAROON);
|
||||
DrawText("Use left and right arrow keys to change current animation", 10, screenHeight - 34, 10, BLACK);
|
||||
DrawText("Use up and down arrow keys to change animation speed", 10, screenHeight - 20, 10, BLACK);
|
||||
DrawText("(c) Guy IQM 3D model by @culacant", screenWidth - 200, screenHeight - 20, 10, GRAY);
|
||||
|
||||
EndDrawing();
|
||||
|
||||
@ -119,7 +119,7 @@ static void DrawModelSkeleton(ModelSkeleton skeleton, ModelAnimPose pose, float
|
||||
{
|
||||
// Loop to (boneCount - 1) because the last one is a special "no bone" bone,
|
||||
// needed to workaround buggy models without a -1, a cube is always drawn at the origin
|
||||
for (int i = 0; i < skeleton.boneCount - 1; i++)
|
||||
for (unsigned int i = 0; i < skeleton.boneCount - 1; i++)
|
||||
{
|
||||
// Display the frame-pose skeleton
|
||||
DrawCube(pose[i].translation, scale*0.05f, scale*0.05f, scale*0.05f, color);
|
||||
|
||||
@ -185,6 +185,9 @@ int main(void)
|
||||
// Unload models data (GPU VRAM)
|
||||
for (int i = 0; i < MAX_VOX_FILES; i++) UnloadModel(models[i]);
|
||||
|
||||
// Unload shader data
|
||||
UnloadShader(shader);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
323
examples/models/models_mesh_uv_painting.c
Normal file
@ -0,0 +1,323 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [models] example - mesh uv painting
|
||||
*
|
||||
* Example demonstrates painting directly onto a mesh's texture: a ray is cast from the
|
||||
* mouse into the scene, the hit triangle is found, and the hit point is converted into
|
||||
* UV space using barycentric interpolation so a brush stroke can be drawn on the texture
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by PanicTitan (@PanicTitan) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 PanicTitan (@PanicTitan)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#include <math.h> // Required for: fabsf(), floorf()
|
||||
#include <stddef.h> // Required for: NULL
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Global Definitions
|
||||
//--------------------------------------------------------------------------------------
|
||||
#define CANVAS_SIZE 512
|
||||
#define PALETTE_COUNT 8
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
typedef enum { TOOL_PAINT = 0, TOOL_PICKER } ToolMode;
|
||||
typedef enum { SHAPE_SPHERE = 0, SHAPE_CUBE, SHAPE_CYLINDER, SHAPE_TORUS } ShapeType;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void ChangeShape(Model *model, BoundingBox *bbox, ShapeType *currentShape, ShapeType newShape, Texture2D canvasTexture);
|
||||
static bool GetMeshHitUV(Ray ray, Model model, BoundingBox bbox, Vector2 *outUV);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [models] example - mesh uv painting");
|
||||
|
||||
Camera3D camera = { 0 };
|
||||
camera.position = (Vector3){ 0.0f, 3.5f, 6.5f };
|
||||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
|
||||
camera.fovy = 45.0f;
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
|
||||
// CPU-side canvas plus the GPU texture it gets pushed to after every stroke
|
||||
Image canvasImage = GenImageColor(CANVAS_SIZE, CANVAS_SIZE, RAYWHITE);
|
||||
Texture2D canvasTexture = LoadTextureFromImage(canvasImage);
|
||||
SetTextureFilter(canvasTexture, TEXTURE_FILTER_BILINEAR);
|
||||
|
||||
Model model = { 0 };
|
||||
BoundingBox modelBBox = { 0 };
|
||||
ShapeType currentShape = SHAPE_SPHERE;
|
||||
ChangeShape(&model, &modelBBox, ¤tShape, SHAPE_SPHERE, canvasTexture);
|
||||
|
||||
ToolMode currentTool = TOOL_PAINT;
|
||||
Color activeColor = RED;
|
||||
int brushRadius = 12;
|
||||
Vector2 lastHitUV = { 0 };
|
||||
bool hasLastHit = false;
|
||||
|
||||
Color palette[PALETTE_COUNT] = { RED, ORANGE, GOLD, LIME, SKYBLUE, PURPLE, DARKGRAY, WHITE };
|
||||
Rectangle uiPanelRec = { 10.0f, 10.0f, 230.0f, 490.0f };
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
bool isMouseOverUI = CheckCollisionPointRec(mousePos, uiPanelRec);
|
||||
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
|
||||
|
||||
if (!isMouseOverUI && IsMouseButtonDown(MOUSE_BUTTON_LEFT))
|
||||
{
|
||||
Ray ray = GetScreenToWorldRay(mousePos, camera);
|
||||
Vector2 hitUV = { 0 };
|
||||
|
||||
if (GetMeshHitUV(ray, model, modelBBox, &hitUV))
|
||||
{
|
||||
int px = (int)(hitUV.x * CANVAS_SIZE);
|
||||
int py = (int)(hitUV.y * CANVAS_SIZE);
|
||||
|
||||
if (currentTool == TOOL_PAINT)
|
||||
{
|
||||
// Stroke from the last hit to this one, guarding against jumps across a UV seam
|
||||
if (hasLastHit && (fabsf(hitUV.x - lastHitUV.x) < 0.25f) && (fabsf(hitUV.y - lastHitUV.y) < 0.25f))
|
||||
{
|
||||
int lastPx = (int)(lastHitUV.x * CANVAS_SIZE);
|
||||
int lastPy = (int)(lastHitUV.y * CANVAS_SIZE);
|
||||
float dist = Vector2Distance((Vector2){ (float)lastPx, (float)lastPy }, (Vector2){ (float)px, (float)py });
|
||||
int steps = (int)(dist / 2.0f) + 1;
|
||||
|
||||
for (int i = 0; i <= steps; i++)
|
||||
{
|
||||
float t = (float)i / (float)steps;
|
||||
ImageDrawCircle(&canvasImage, (int)Lerp((float)lastPx, (float)px, t),
|
||||
(int)Lerp((float)lastPy, (float)py, t), brushRadius, activeColor);
|
||||
}
|
||||
}
|
||||
else ImageDrawCircle(&canvasImage, px, py, brushRadius, activeColor);
|
||||
|
||||
UpdateTexture(canvasTexture, canvasImage.data);
|
||||
lastHitUV = hitUV;
|
||||
hasLastHit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeColor = GetImageColor(canvasImage, px, py);
|
||||
currentTool = TOOL_PAINT;
|
||||
hasLastHit = false;
|
||||
}
|
||||
}
|
||||
else hasLastHit = false;
|
||||
}
|
||||
else hasLastHit = false;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground((Color){ 30, 32, 40, 255 });
|
||||
|
||||
BeginMode3D(camera);
|
||||
DrawModel(model, Vector3Zero(), 1.0f, WHITE);
|
||||
DrawGrid(10, 1.0f);
|
||||
EndMode3D();
|
||||
|
||||
// Side panel
|
||||
DrawRectangleRec(uiPanelRec, Fade(BLACK, 0.8f));
|
||||
DrawRectangleLinesEx(uiPanelRec, 2.0f, DARKGRAY);
|
||||
DrawText("MESH UV PAINTER", 25, 22, 20, GOLD);
|
||||
|
||||
// Tool selection toggles
|
||||
bool paintActive = (currentTool == TOOL_PAINT);
|
||||
bool pickerActive = (currentTool == TOOL_PICKER);
|
||||
if (GuiToggle((Rectangle){ 25, 55, 95, 32 }, "PAINT", &paintActive)) currentTool = TOOL_PAINT;
|
||||
if (GuiToggle((Rectangle){ 125, 55, 95, 32 }, "PICKER", &pickerActive)) currentTool = TOOL_PICKER;
|
||||
|
||||
// Shape selection toggles
|
||||
DrawText("Mesh Shape:", 25, 100, 10, LIGHTGRAY);
|
||||
bool sphereActive = (currentShape == SHAPE_SPHERE);
|
||||
bool cubeActive = (currentShape == SHAPE_CUBE);
|
||||
bool cylinderActive = (currentShape == SHAPE_CYLINDER);
|
||||
bool torusActive = (currentShape == SHAPE_TORUS);
|
||||
|
||||
if (GuiToggle((Rectangle){ 25, 120, 95, 28 }, "SPHERE", &sphereActive))
|
||||
ChangeShape(&model, &modelBBox, ¤tShape, SHAPE_SPHERE, canvasTexture);
|
||||
if (GuiToggle((Rectangle){ 125, 120, 95, 28 }, "CUBE", &cubeActive))
|
||||
ChangeShape(&model, &modelBBox, ¤tShape, SHAPE_CUBE, canvasTexture);
|
||||
if (GuiToggle((Rectangle){ 25, 153, 95, 28 }, "CYLINDER", &cylinderActive))
|
||||
ChangeShape(&model, &modelBBox, ¤tShape, SHAPE_CYLINDER, canvasTexture);
|
||||
if (GuiToggle((Rectangle){ 125, 153, 95, 28 }, "TORUS", &torusActive))
|
||||
ChangeShape(&model, &modelBBox, ¤tShape, SHAPE_TORUS, canvasTexture);
|
||||
|
||||
// Color display
|
||||
DrawText("Active Color:", 25, 195, 10, LIGHTGRAY);
|
||||
DrawRectangle(125, 193, 95, 20, activeColor);
|
||||
DrawRectangleLines(125, 193, 95, 20, WHITE);
|
||||
|
||||
// Color swatches
|
||||
DrawText("Palette Swatches:", 25, 225, 10, LIGHTGRAY);
|
||||
for (int i = 0; i < PALETTE_COUNT; i++)
|
||||
{
|
||||
Rectangle swatchRec = { 25.0f + (i%4)*48, 245.0f + (i/4)*45, 40.0f, 38.0f };
|
||||
DrawRectangleRec(swatchRec, palette[i]);
|
||||
DrawRectangleLinesEx(swatchRec, 1.0f, WHITE);
|
||||
if (CheckCollisionPointRec(mousePos, swatchRec) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) activeColor = palette[i];
|
||||
}
|
||||
|
||||
// Brush size buttons
|
||||
DrawText(TextFormat("Brush Size: %dpx", brushRadius), 25, 345, 10, LIGHTGRAY);
|
||||
if (GuiButton((Rectangle){ 25, 365, 95, 30 }, "SIZE -") && (brushRadius > 2)) brushRadius -= 2;
|
||||
if (GuiButton((Rectangle){ 125, 365, 95, 30 }, "SIZE +") && (brushRadius < 64)) brushRadius += 2;
|
||||
|
||||
// Canvas action buttons
|
||||
if (GuiButton((Rectangle){ 25, 410, 95, 30 }, "CLEAR"))
|
||||
{
|
||||
ImageClearBackground(&canvasImage, RAYWHITE);
|
||||
UpdateTexture(canvasTexture, canvasImage.data);
|
||||
}
|
||||
if (GuiButton((Rectangle){ 125, 410, 95, 30 }, "FILL"))
|
||||
{
|
||||
ImageClearBackground(&canvasImage, activeColor);
|
||||
UpdateTexture(canvasTexture, canvasImage.data);
|
||||
}
|
||||
|
||||
DrawText("Left click: paint / pick color | Right drag: orbit camera", 260, screenHeight - 25, 10, RAYWHITE);
|
||||
DrawFPS(screenWidth - 90, 15);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModel(model);
|
||||
UnloadImage(canvasImage);
|
||||
UnloadTexture(canvasTexture);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Unloads the current model and builds a new primitive shape in its place, sharing the
|
||||
// same canvas texture, and recomputes the transformed bounding box used for ray testing
|
||||
static void ChangeShape(Model *model, BoundingBox *bbox, ShapeType *currentShape, ShapeType newShape, Texture2D canvasTexture)
|
||||
{
|
||||
UnloadModel(*model);
|
||||
|
||||
Mesh mesh = { 0 };
|
||||
|
||||
switch (newShape)
|
||||
{
|
||||
case SHAPE_SPHERE: mesh = GenMeshSphere(1.5f, 32, 32); break;
|
||||
case SHAPE_CUBE: mesh = GenMeshCube(2.2f, 2.2f, 2.2f); break;
|
||||
case SHAPE_CYLINDER: mesh = GenMeshCylinder(1.2f, 2.5f, 24); break;
|
||||
case SHAPE_TORUS: mesh = GenMeshTorus(0.6f, 1.6f, 24, 36); break;
|
||||
default: mesh = GenMeshSphere(1.5f, 32, 32); break;
|
||||
}
|
||||
|
||||
*model = LoadModelFromMesh(mesh);
|
||||
|
||||
// GenMeshCylinder builds upward from y = 0; shift it down to center on the origin
|
||||
if (newShape == SHAPE_CYLINDER) model->transform = MatrixTranslate(0.0f, -1.25f, 0.0f);
|
||||
|
||||
model->materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = canvasTexture;
|
||||
|
||||
BoundingBox box = GetMeshBoundingBox(model->meshes[0]);
|
||||
box.min = Vector3Transform(box.min, model->transform);
|
||||
box.max = Vector3Transform(box.max, model->transform);
|
||||
*bbox = box;
|
||||
|
||||
*currentShape = newShape;
|
||||
}
|
||||
|
||||
// Raycasts against the model's mesh triangles and returns the UV coordinate of the
|
||||
// closest hit, interpolated from the hit triangle's vertices with barycentric weights
|
||||
static bool GetMeshHitUV(Ray ray, Model model, BoundingBox bbox, Vector2 *outUV)
|
||||
{
|
||||
if (!GetRayCollisionBox(ray, bbox).hit) return false; // Fast reject
|
||||
|
||||
Mesh mesh = model.meshes[0];
|
||||
float closestDistance = 1e9f;
|
||||
bool found = false;
|
||||
Vector2 hitUV = { 0 };
|
||||
|
||||
for (int tri = 0; tri < mesh.triangleCount; tri++)
|
||||
{
|
||||
int i0, i1, i2;
|
||||
|
||||
if (mesh.indices != NULL)
|
||||
{
|
||||
i0 = mesh.indices[3*tri + 0];
|
||||
i1 = mesh.indices[3*tri + 1];
|
||||
i2 = mesh.indices[3*tri + 2];
|
||||
}
|
||||
else { i0 = 3*tri; i1 = 3*tri + 1; i2 = 3*tri + 2; }
|
||||
|
||||
Vector3 a = Vector3Transform((Vector3){ mesh.vertices[3*i0], mesh.vertices[3*i0 + 1], mesh.vertices[3*i0 + 2] }, model.transform);
|
||||
Vector3 b = Vector3Transform((Vector3){ mesh.vertices[3*i1], mesh.vertices[3*i1 + 1], mesh.vertices[3*i1 + 2] }, model.transform);
|
||||
Vector3 c = Vector3Transform((Vector3){ mesh.vertices[3*i2], mesh.vertices[3*i2 + 1], mesh.vertices[3*i2 + 2] }, model.transform);
|
||||
|
||||
RayCollision hit = GetRayCollisionTriangle(ray, a, b, c);
|
||||
|
||||
if (hit.hit && (hit.distance < closestDistance))
|
||||
{
|
||||
closestDistance = hit.distance;
|
||||
found = true;
|
||||
|
||||
Vector2 uvA = { mesh.texcoords[2*i0], mesh.texcoords[2*i0 + 1] };
|
||||
Vector2 uvB = { mesh.texcoords[2*i1], mesh.texcoords[2*i1 + 1] };
|
||||
Vector2 uvC = { mesh.texcoords[2*i2], mesh.texcoords[2*i2 + 1] };
|
||||
|
||||
Vector3 w = Vector3Barycenter(hit.point, a, b, c);
|
||||
|
||||
hitUV.x = w.x*uvA.x + w.y*uvB.x + w.z*uvC.x;
|
||||
hitUV.y = w.x*uvA.y + w.y*uvB.y + w.z*uvC.y;
|
||||
|
||||
// Wrap into [0, 1] in case of minor floating point drift at UV seams
|
||||
hitUV.x -= floorf(hitUV.x);
|
||||
hitUV.y -= floorf(hitUV.y);
|
||||
}
|
||||
}
|
||||
|
||||
if (found && (outUV != NULL)) *outUV = hitUV;
|
||||
|
||||
return found;
|
||||
}
|
||||
BIN
examples/models/models_mesh_uv_painting.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
504
examples/models/models_procedural_decals.c
Normal file
@ -0,0 +1,504 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [models] example - procedural decals
|
||||
*
|
||||
* Example demonstrates projecting decals onto a 3D mesh surface by transforming the
|
||||
* mesh's own triangles into the decal's local space and clipping them against a box,
|
||||
* using only procedurally generated geometry and textures (no external resource files)
|
||||
*
|
||||
* NOTE: This is the same clip-space decal projection idea used by models_decals.c
|
||||
* (in turn based on three.js' DecalGeometry), applied here to a generated mesh and
|
||||
* generated textures instead of a loaded model, so the example is fully self-contained
|
||||
*
|
||||
* Example complexity rating: [★★★★] 4/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by PanicTitan (@PanicTitan) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 PanicTitan (@PanicTitan)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
#include "raymath.h"
|
||||
|
||||
#include <stddef.h> // Required for: NULL
|
||||
#include <string.h> // Required for: memcpy()
|
||||
#include <math.h> // Required for: fabsf(), fminf()
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Global Definitions
|
||||
//--------------------------------------------------------------------------------------
|
||||
#define MAX_DECALS 256
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Growable triangle-soup buffer used while building a clipped decal mesh
|
||||
typedef struct MeshBuilder {
|
||||
int vertexCount;
|
||||
int vertexCapacity;
|
||||
Vector3 *vertices;
|
||||
Vector2 *uvs;
|
||||
} MeshBuilder;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 v0, Vector3 v1, Vector3 v2);
|
||||
static void FreeMeshBuilder(MeshBuilder *mb);
|
||||
static Mesh BuildMesh(MeshBuilder *mb);
|
||||
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s);
|
||||
static Mesh GenMeshDecal(Model model, Matrix projection, float decalSize, float decalOffset);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [models] example - procedural decals");
|
||||
|
||||
Camera3D camera = { 0 };
|
||||
camera.position = (Vector3){ 0.0f, 2.5f, 5.0f };
|
||||
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
|
||||
camera.fovy = 45.0f;
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
|
||||
// Target model: a procedurally generated knot with a checkerboard skin
|
||||
Model model = LoadModelFromMesh(GenMeshTorus(0.8f, 1.8f, 32, 64));
|
||||
|
||||
Image checkerImage = GenImageChecked(512, 512, 32, 32, LIGHTGRAY, GRAY);
|
||||
Texture2D modelTexture = LoadTextureFromImage(checkerImage);
|
||||
UnloadImage(checkerImage);
|
||||
SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR);
|
||||
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture;
|
||||
|
||||
BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]);
|
||||
camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f);
|
||||
|
||||
float modelSize = fminf(fminf(fabsf(modelBBox.max.x - modelBBox.min.x),
|
||||
fabsf(modelBBox.max.y - modelBBox.min.y)), fabsf(modelBBox.max.z - modelBBox.min.z));
|
||||
|
||||
float decalSize = modelSize*0.35f;
|
||||
float decalOffset = 0.01f;
|
||||
|
||||
// Translucent cube previewing where the next decal will land
|
||||
Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize));
|
||||
placementCube.materials[0].maps[0].color = LIME;
|
||||
|
||||
// Decal texture: a procedurally drawn target/bullseye, no image file needed
|
||||
Image decalImage = GenImageColor(128, 128, BLANK);
|
||||
ImageDrawCircle(&decalImage, 64, 64, 60, RED);
|
||||
ImageDrawCircle(&decalImage, 64, 64, 45, WHITE);
|
||||
ImageDrawCircle(&decalImage, 64, 64, 30, RED);
|
||||
ImageDrawCircle(&decalImage, 64, 64, 15, YELLOW);
|
||||
|
||||
Texture2D decalTexture = LoadTextureFromImage(decalImage);
|
||||
UnloadImage(decalImage);
|
||||
SetTextureFilter(decalTexture, TEXTURE_FILTER_BILINEAR);
|
||||
|
||||
Material decalMaterial = LoadMaterialDefault();
|
||||
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture;
|
||||
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
|
||||
|
||||
bool showModel = true;
|
||||
Model decals[MAX_DECALS] = { 0 };
|
||||
int decalCount = 0;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON);
|
||||
|
||||
// Cast a ray from the mouse and keep the closest point it hits on the model
|
||||
Ray ray = GetScreenToWorldRay(GetMousePosition(), camera);
|
||||
RayCollision collision = { 0 };
|
||||
|
||||
if (GetRayCollisionBox(ray, modelBBox).hit && (decalCount < MAX_DECALS))
|
||||
{
|
||||
for (int m = 0; m < model.meshCount; m++)
|
||||
{
|
||||
RayCollision meshHit = GetRayCollisionMesh(ray, model.meshes[m], model.transform);
|
||||
if (meshHit.hit && (!collision.hit || (meshHit.distance < collision.distance))) collision = meshHit;
|
||||
}
|
||||
}
|
||||
|
||||
// Project a new decal at the hit point, facing along the surface normal
|
||||
if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (decalCount < MAX_DECALS))
|
||||
{
|
||||
Vector3 lookTarget = Vector3Add(collision.point, collision.normal);
|
||||
Matrix splat = MatrixLookAt(collision.point, lookTarget, (Vector3){ 0.0f, 1.0f, 0.0f });
|
||||
splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*(float)GetRandomValue(-180, 180)));
|
||||
|
||||
Mesh decalMesh = GenMeshDecal(model, splat, decalSize, decalOffset);
|
||||
|
||||
if (decalMesh.vertexCount > 0)
|
||||
{
|
||||
decals[decalCount] = LoadModelFromMesh(decalMesh);
|
||||
decals[decalCount].materials[0].maps[0] = decalMaterial.maps[0];
|
||||
decalCount++;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
if (showModel) DrawModel(model, Vector3Zero(), 1.0f, WHITE);
|
||||
|
||||
for (int i = 0; i < decalCount; i++) DrawModel(decals[i], Vector3Zero(), 1.0f, WHITE);
|
||||
|
||||
// Preview cube at the surface point currently under the mouse
|
||||
if (collision.hit)
|
||||
{
|
||||
Vector3 lookTarget = Vector3Add(collision.point, collision.normal);
|
||||
Matrix splat = MatrixLookAt(collision.point, lookTarget, (Vector3){ 0.0f, 1.0f, 0.0f });
|
||||
placementCube.transform = MatrixInvert(splat);
|
||||
DrawModel(placementCube, Vector3Zero(), 1.0f, Fade(WHITE, 0.5f));
|
||||
}
|
||||
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// Vertex/triangle counts: base model vs total once decal geometry is added
|
||||
int baseVertices = 0, baseTriangles = 0;
|
||||
for (int i = 0; i < model.meshCount; i++)
|
||||
{
|
||||
baseVertices += model.meshes[i].vertexCount;
|
||||
baseTriangles += model.meshes[i].triangleCount;
|
||||
}
|
||||
|
||||
int totalVertices = baseVertices, totalTriangles = baseTriangles;
|
||||
for (int i = 0; i < decalCount; i++)
|
||||
{
|
||||
totalVertices += decals[i].meshes[0].vertexCount;
|
||||
totalTriangles += decals[i].meshes[0].triangleCount;
|
||||
}
|
||||
|
||||
int statX = screenWidth - 280;
|
||||
DrawText("Vertices", statX + 90, 10, 10, LIME);
|
||||
DrawText("Triangles", statX + 180, 10, 10, LIME);
|
||||
DrawText("Base Model", statX, 25, 10, LIME);
|
||||
DrawText(TextFormat("%d", baseVertices), statX + 90, 25, 10, LIME);
|
||||
DrawText(TextFormat("%d", baseTriangles), statX + 180, 25, 10, LIME);
|
||||
DrawText("TOTAL", statX, 40, 10, LIME);
|
||||
DrawText(TextFormat("%d", totalVertices), statX + 90, 40, 10, LIME);
|
||||
DrawText(TextFormat("%d", totalTriangles), statX + 180, 40, 10, LIME);
|
||||
|
||||
if (GuiButton((Rectangle){ 10, screenHeight - 80.0f, 100, 40 }, showModel ? "Hide Model" : "Show Model"))
|
||||
showModel = !showModel;
|
||||
|
||||
if (GuiButton((Rectangle){ 120, screenHeight - 80.0f, 100, 40 }, "Clear Decals"))
|
||||
{
|
||||
for (int i = 0; i < decalCount; i++) UnloadModel(decals[i]);
|
||||
decalCount = 0;
|
||||
}
|
||||
|
||||
DrawText("Left click: place decal | Right drag: orbit camera", 10, screenHeight - 25, 10, DARKGRAY);
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
for (int i = 0; i < decalCount; i++) UnloadModel(decals[i]);
|
||||
|
||||
UnloadModel(placementCube);
|
||||
UnloadTexture(decalTexture);
|
||||
UnloadTexture(modelTexture);
|
||||
UnloadModel(model);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Appends a triangle to a growable mesh builder buffer, growing it in fixed-size chunks
|
||||
static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 v0, Vector3 v1, Vector3 v2)
|
||||
{
|
||||
if (mb->vertexCapacity <= (mb->vertexCount + 3))
|
||||
{
|
||||
int newVertexCapacity = (1 + (mb->vertexCapacity/256))*256;
|
||||
Vector3 *newVertices = (Vector3 *)MemAlloc(newVertexCapacity*sizeof(Vector3));
|
||||
|
||||
if (mb->vertexCapacity > 0)
|
||||
{
|
||||
memcpy(newVertices, mb->vertices, mb->vertexCount*sizeof(Vector3));
|
||||
MemFree(mb->vertices);
|
||||
}
|
||||
|
||||
mb->vertices = newVertices;
|
||||
mb->vertexCapacity = newVertexCapacity;
|
||||
}
|
||||
|
||||
int index = mb->vertexCount;
|
||||
mb->vertexCount += 3;
|
||||
|
||||
mb->vertices[index + 0] = v0;
|
||||
mb->vertices[index + 1] = v1;
|
||||
mb->vertices[index + 2] = v2;
|
||||
}
|
||||
|
||||
// Frees a mesh builder's backing buffers
|
||||
static void FreeMeshBuilder(MeshBuilder *mb)
|
||||
{
|
||||
if (mb->vertices != NULL) MemFree(mb->vertices);
|
||||
if (mb->uvs != NULL) MemFree(mb->uvs);
|
||||
*mb = (MeshBuilder){ 0 };
|
||||
}
|
||||
|
||||
// Converts a mesh builder's triangle soup into a standard uploaded raylib Mesh
|
||||
static Mesh BuildMesh(MeshBuilder *mb)
|
||||
{
|
||||
Mesh outMesh = { 0 };
|
||||
|
||||
outMesh.vertexCount = mb->vertexCount;
|
||||
outMesh.triangleCount = mb->vertexCount/3;
|
||||
outMesh.vertices = (float *)MemAlloc(outMesh.vertexCount*3*sizeof(float));
|
||||
if (mb->uvs != NULL) outMesh.texcoords = (float *)MemAlloc(outMesh.vertexCount*2*sizeof(float));
|
||||
|
||||
for (int i = 0; i < mb->vertexCount; i++)
|
||||
{
|
||||
outMesh.vertices[3*i + 0] = mb->vertices[i].x;
|
||||
outMesh.vertices[3*i + 1] = mb->vertices[i].y;
|
||||
outMesh.vertices[3*i + 2] = mb->vertices[i].z;
|
||||
|
||||
if (mb->uvs != NULL)
|
||||
{
|
||||
outMesh.texcoords[2*i + 0] = mb->uvs[i].x;
|
||||
outMesh.texcoords[2*i + 1] = mb->uvs[i].y;
|
||||
}
|
||||
}
|
||||
|
||||
UploadMesh(&outMesh, false);
|
||||
|
||||
return outMesh;
|
||||
}
|
||||
|
||||
// Clips the segment [v0, v1] against the plane p.x = s, returning the intersection point
|
||||
static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s)
|
||||
{
|
||||
float d0 = Vector3DotProduct(v0, p) - s;
|
||||
float d1 = Vector3DotProduct(v1, p) - s;
|
||||
float t = d0/(d0 - d1);
|
||||
|
||||
return Vector3Lerp(v0, v1, t);
|
||||
}
|
||||
|
||||
// Builds a decal mesh: the model's triangles are transformed into the decal's local space
|
||||
// (so the decal sits at the origin, facing +Z) and clipped against a decalSize-sided box,
|
||||
// following the same clip-space projection idea used by engines' decal systems (and by
|
||||
// three.js' DecalGeometry, which the technique is commonly traced back to). What's left
|
||||
// after clipping becomes the decal's own small mesh, UV-mapped from its local coordinates
|
||||
static Mesh GenMeshDecal(Model model, Matrix projection, float decalSize, float decalOffset)
|
||||
{
|
||||
Matrix invProj = MatrixInvert(projection);
|
||||
MeshBuilder meshBuilders[2] = { 0 };
|
||||
int mbIndex = 0;
|
||||
|
||||
// Gather triangles that land anywhere near the decal box; this is a loose, cheap
|
||||
// pre-filter meant to skip most of the model, the precise clip happens below
|
||||
for (int meshIndex = 0; meshIndex < model.meshCount; meshIndex++)
|
||||
{
|
||||
Mesh mesh = model.meshes[meshIndex];
|
||||
|
||||
for (int tri = 0; tri < mesh.triangleCount; tri++)
|
||||
{
|
||||
Vector3 vertices[3] = { 0 };
|
||||
|
||||
if (mesh.indices == NULL)
|
||||
{
|
||||
for (int v = 0; v < 3; v++)
|
||||
{
|
||||
vertices[v] = (Vector3){
|
||||
mesh.vertices[3*3*tri + 3*v + 0],
|
||||
mesh.vertices[3*3*tri + 3*v + 1],
|
||||
mesh.vertices[3*3*tri + 3*v + 2]
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int v = 0; v < 3; v++)
|
||||
{
|
||||
int idx = mesh.indices[3*tri + v];
|
||||
vertices[v] = (Vector3){
|
||||
mesh.vertices[3*idx + 0],
|
||||
mesh.vertices[3*idx + 1],
|
||||
mesh.vertices[3*idx + 2]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
int insideCount = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Vector3 v = Vector3Transform(vertices[i], projection);
|
||||
if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++;
|
||||
vertices[i] = v;
|
||||
}
|
||||
|
||||
if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices[0], vertices[1], vertices[2]);
|
||||
}
|
||||
}
|
||||
|
||||
// Clip the surviving triangles against each of the decal box's 6 faces in turn
|
||||
Vector3 planes[6] = {
|
||||
{ 1, 0, 0 }, { -1, 0, 0 },
|
||||
{ 0, 1, 0 }, { 0, -1, 0 },
|
||||
{ 0, 0, 1 }, { 0, 0, -1 }
|
||||
};
|
||||
|
||||
for (int face = 0; face < 6; face++)
|
||||
{
|
||||
mbIndex = 1 - mbIndex;
|
||||
|
||||
MeshBuilder *inMesh = &meshBuilders[1 - mbIndex];
|
||||
MeshBuilder *outMesh = &meshBuilders[mbIndex];
|
||||
|
||||
outMesh->vertexCount = 0;
|
||||
float s = 0.5f*decalSize;
|
||||
|
||||
for (int i = 0; i < inMesh->vertexCount; i += 3)
|
||||
{
|
||||
Vector3 nV1, nV2, nV3, nV4;
|
||||
|
||||
float d1 = Vector3DotProduct(inMesh->vertices[i + 0], planes[face]) - s;
|
||||
float d2 = Vector3DotProduct(inMesh->vertices[i + 1], planes[face]) - s;
|
||||
float d3 = Vector3DotProduct(inMesh->vertices[i + 2], planes[face]) - s;
|
||||
|
||||
int v1Out = (d1 > 0);
|
||||
int v2Out = (d2 > 0);
|
||||
int v3Out = (d3 > 0);
|
||||
int total = v1Out + v2Out + v3Out;
|
||||
|
||||
switch (total)
|
||||
{
|
||||
case 0:
|
||||
// Whole triangle is inside this face, keep it as-is
|
||||
AddTriangleToMeshBuilder(outMesh, inMesh->vertices[i], inMesh->vertices[i + 1], inMesh->vertices[i + 2]);
|
||||
break;
|
||||
case 1:
|
||||
// One corner is outside; clip it off, turning the triangle into a quad
|
||||
if (v1Out)
|
||||
{
|
||||
nV1 = inMesh->vertices[i + 1];
|
||||
nV2 = inMesh->vertices[i + 2];
|
||||
nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s);
|
||||
nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s);
|
||||
}
|
||||
|
||||
if (v2Out)
|
||||
{
|
||||
nV1 = inMesh->vertices[i];
|
||||
nV2 = inMesh->vertices[i + 2];
|
||||
nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s);
|
||||
nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s);
|
||||
|
||||
AddTriangleToMeshBuilder(outMesh, nV3, nV2, nV1);
|
||||
AddTriangleToMeshBuilder(outMesh, nV2, nV3, nV4);
|
||||
break;
|
||||
}
|
||||
|
||||
if (v3Out)
|
||||
{
|
||||
nV1 = inMesh->vertices[i];
|
||||
nV2 = inMesh->vertices[i + 1];
|
||||
nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s);
|
||||
nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s);
|
||||
}
|
||||
|
||||
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
|
||||
AddTriangleToMeshBuilder(outMesh, nV4, nV3, nV2);
|
||||
break;
|
||||
case 2:
|
||||
// Two corners are outside; only the small corner near the surviving vertex remains
|
||||
if (!v1Out)
|
||||
{
|
||||
nV1 = inMesh->vertices[i];
|
||||
nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
|
||||
nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
|
||||
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
|
||||
}
|
||||
|
||||
if (!v2Out)
|
||||
{
|
||||
nV1 = inMesh->vertices[i + 1];
|
||||
nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s);
|
||||
nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
|
||||
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
|
||||
}
|
||||
|
||||
if (!v3Out)
|
||||
{
|
||||
nV1 = inMesh->vertices[i + 2];
|
||||
nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s);
|
||||
nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s);
|
||||
AddTriangleToMeshBuilder(outMesh, nV1, nV2, nV3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// All 3 corners are outside this face, the triangle is fully clipped away
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MeshBuilder *finalMesh = &meshBuilders[mbIndex];
|
||||
Mesh decalMesh = { 0 };
|
||||
|
||||
if (finalMesh->vertexCount > 0)
|
||||
{
|
||||
finalMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*finalMesh->vertexCount);
|
||||
|
||||
for (int i = 0; i < finalMesh->vertexCount; i++)
|
||||
{
|
||||
// Clipped coordinates run roughly (-decalSize/2 .. decalSize/2); remap to (0..1)
|
||||
finalMesh->uvs[i].x = (finalMesh->vertices[i].x/decalSize + 0.5f);
|
||||
finalMesh->uvs[i].y = (finalMesh->vertices[i].y/decalSize + 0.5f);
|
||||
|
||||
// Nudge slightly along the normal so the decal doesn't z-fight with the surface
|
||||
finalMesh->vertices[i].z -= decalOffset;
|
||||
finalMesh->vertices[i] = Vector3Transform(finalMesh->vertices[i], invProj);
|
||||
}
|
||||
|
||||
decalMesh = BuildMesh(finalMesh);
|
||||
}
|
||||
|
||||
FreeMeshBuilder(&meshBuilders[0]);
|
||||
FreeMeshBuilder(&meshBuilders[1]);
|
||||
|
||||
return decalMesh;
|
||||
}
|
||||
BIN
examples/models/models_procedural_decals.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
@ -180,8 +180,8 @@ int main(void)
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadShader(skybox.materials[0].shader);
|
||||
UnloadTexture(skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture);
|
||||
|
||||
UnloadModel(skybox); // Unload skybox model
|
||||
UnloadShader(shdrCubemap);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
153
examples/others/gl_scissor_shapes.c
Normal file
@ -0,0 +1,153 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [others] example - scissor shapes
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.0
|
||||
*
|
||||
* Example contributed by David Buzatto (@davidbuzatto) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2026 David Buzatto (@davidbuzatto)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "rlgl.h"
|
||||
|
||||
#include <math.h> // Required for: sinf()
|
||||
|
||||
// BeginScissorMode() only clips to an axis-aligned rectangle, since it maps
|
||||
// directly to glScissor. Clipping to an arbitrary shape (the same idea as
|
||||
// Graphics2D.setClip(Shape) in Java2D) needs the stencil buffer instead:
|
||||
// the clip shape is rasterized into the stencil buffer first, then further
|
||||
// draws are only let through where the stencil was written.
|
||||
//
|
||||
// rlgl has no stencil wrapper (see raysan5/raylib discussion #2964), so this
|
||||
// example calls the handful of OpenGL 1.0 stencil functions directly - they
|
||||
// don't need glad/extension loading, same as glScissor doesn't.
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#if !defined(APIENTRY)
|
||||
#if defined(_WIN32)
|
||||
#define APIENTRY __stdcall
|
||||
#else
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(WINGDIAPI) && defined(_WIN32)
|
||||
#define WINGDIAPI __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
// mask is a callback instead of a fixed shape, so the clip region can be any
|
||||
// combination of Draw* calls (circle, polygon, text, several shapes together)
|
||||
typedef void (*ScissorMaskDrawFunc)(void *userData);
|
||||
|
||||
static void BeginScissorModeShape(ScissorMaskDrawFunc mask, void *userData)
|
||||
{
|
||||
rlDrawRenderBatchActive(); // Flush before touching stencil state
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilMask(0xFF);
|
||||
|
||||
// Pass 1: rasterize the mask into the stencil buffer only, no color write
|
||||
rlColorMask(false, false, false, false);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
mask(userData);
|
||||
rlDrawRenderBatchActive(); // Flush the mask draw
|
||||
|
||||
// Pass 2: subsequent draws only survive where the stencil was written
|
||||
rlColorMask(true, true, true, true);
|
||||
glStencilFunc(GL_EQUAL, 1, 0xFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
}
|
||||
|
||||
static void EndScissorModeShape(void)
|
||||
{
|
||||
rlDrawRenderBatchActive();
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
// Two example mask shapes, drawn in WHITE (the color is irrelevant here,
|
||||
// only the stencil write from pass 1 matters)
|
||||
typedef struct { Vector2 center; float radius; } CircleMask;
|
||||
static void DrawCircleMask(void *userData)
|
||||
{
|
||||
CircleMask *m = (CircleMask *)userData;
|
||||
DrawCircleV(m->center, m->radius, WHITE);
|
||||
}
|
||||
|
||||
typedef struct { Vector2 center; float radius; int sides; } PolyMask;
|
||||
static void DrawPolyMask(void *userData)
|
||||
{
|
||||
PolyMask *m = (PolyMask *)userData;
|
||||
DrawPoly(m->center, m->sides, m->radius, 0.0f, WHITE);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [others] example - scissor shapes");
|
||||
|
||||
Vector2 circleCenter = { screenWidth/2.0f - 120, screenHeight/2.0f };
|
||||
Vector2 hexCenter = { screenWidth/2.0f + 120, screenHeight/2.0f };
|
||||
float maskRadius = 100.0f;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
circleCenter.y = screenHeight/2.0f + sinf((float)GetTime())*40.0f;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
// Circle-shaped clip: the full-screen rectangle only shows inside the circle
|
||||
CircleMask circleMask = { circleCenter, maskRadius };
|
||||
BeginScissorModeShape(DrawCircleMask, &circleMask);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, BLUE);
|
||||
EndScissorModeShape();
|
||||
|
||||
// Hexagon-shaped clip: same mechanism, a different mask shape
|
||||
PolyMask hexMask = { hexCenter, maskRadius, 6 };
|
||||
BeginScissorModeShape(DrawPolyMask, &hexMask);
|
||||
DrawRectangle(0, 0, screenWidth, screenHeight, ORANGE);
|
||||
EndScissorModeShape();
|
||||
|
||||
DrawText("BeginScissorMode() only clips to a rectangle (glScissor)", 10, 10, 10, DARKGRAY);
|
||||
DrawText("This clips to arbitrary shapes instead, using the stencil buffer", 10, 25, 10, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
examples/others/gl_scissor_shapes.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
@ -28,7 +28,7 @@
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL)
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) || defined(PLATFORM_DESKTOP_RGFW)
|
||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||
#include "glad_gles2.h" // Required for: OpenGL functionality
|
||||
#define glGenVertexArrays glGenVertexArraysOES
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
*
|
||||
* APPLE COMPILATION:
|
||||
* gcc -o rlgl_standalone rlgl_standalone.c -I../../src -Iexternal/include -Lexternal/lib \
|
||||
* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa
|
||||
* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa -framework QuartzCore
|
||||
* -Wno-deprecated-declarations -std=c99 -DGRAPHICS_API_OPENGL_33
|
||||
*
|
||||
*
|
||||
|
||||
44
examples/shaders/resources/shaders/glsl100/lights_bloom.fs
Normal file
@ -0,0 +1,44 @@
|
||||
#version 100
|
||||
|
||||
precision mediump float;
|
||||
|
||||
// Input values from vertex shader
|
||||
varying vec3 fragPosition;
|
||||
varying vec3 fragNormal;
|
||||
varying vec2 fragTexCoord;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec3 viewPos;
|
||||
uniform vec3 lightPositions[8];
|
||||
uniform vec3 lightColors[8];
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texColor = texture2D(texture0, fragTexCoord);
|
||||
vec3 norm = normalize(fragNormal);
|
||||
vec3 viewDir = normalize(viewPos - fragPosition);
|
||||
|
||||
vec3 ambient = 0.05*texColor.rgb;
|
||||
vec3 totalDiffuse = vec3(0.0);
|
||||
vec3 totalSpecular = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
vec3 lightDir = normalize(lightPositions[i] - fragPosition);
|
||||
float dist = length(lightPositions[i] - fragPosition);
|
||||
float attenuation = 1.0/(1.0 + 0.8*dist + 0.4*dist*dist);
|
||||
|
||||
// Diffuse shading
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
totalDiffuse += diff*lightColors[i]*attenuation*1.2;
|
||||
|
||||
// Blinn-Phong specular
|
||||
vec3 halfwayDir = normalize(lightDir + viewDir);
|
||||
float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0);
|
||||
totalSpecular += spec*lightColors[i]*attenuation*0.8;
|
||||
}
|
||||
|
||||
vec3 result = ambient + (totalDiffuse*texColor.rgb) + totalSpecular;
|
||||
gl_FragColor = vec4(result, texColor.a);
|
||||
}
|
||||
23
examples/shaders/resources/shaders/glsl100/lights_bloom.vs
Normal file
@ -0,0 +1,23 @@
|
||||
#version 100
|
||||
|
||||
// Input vertex attributes
|
||||
attribute vec3 vertexPosition;
|
||||
attribute vec2 vertexTexCoord;
|
||||
attribute vec3 vertexNormal;
|
||||
|
||||
// Output values to fragment shader
|
||||
varying vec3 fragPosition;
|
||||
varying vec3 fragNormal;
|
||||
varying vec2 fragTexCoord;
|
||||
|
||||
// Input uniform values
|
||||
uniform mat4 mvp;
|
||||
uniform mat4 matModel;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||
fragNormal = normalize(vec3(matModel*vec4(vertexNormal, 0.0)));
|
||||
fragTexCoord = vertexTexCoord;
|
||||
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
#version 100
|
||||
|
||||
precision mediump float;
|
||||
|
||||
varying vec2 fragTexCoord;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture2D(texture0, fragTexCoord);
|
||||
|
||||
// High-pass threshold blur: only pixels brighter than 0.75 in any channel contribute
|
||||
vec4 bloom = vec4(0.0);
|
||||
vec2 texel = vec2(1.0/1280.0, 1.0/720.0)*2.5;
|
||||
|
||||
for (int x = -2; x <= 2; x++)
|
||||
{
|
||||
for (int y = -2; y <= 2; y++)
|
||||
{
|
||||
vec4 smp = texture2D(texture0, fragTexCoord + vec2(float(x), float(y))*texel);
|
||||
float brightness = max(smp.r, max(smp.g, smp.b));
|
||||
if (brightness > 0.75) bloom += smp;
|
||||
}
|
||||
}
|
||||
bloom /= 25.0;
|
||||
|
||||
// Combine original with the bloom glow, then Reinhard tone-map back to [0, 1]
|
||||
vec3 hdr = color.rgb + bloom.rgb*1.2;
|
||||
vec3 ldr = hdr/(hdr + vec3(1.0));
|
||||
|
||||
gl_FragColor = vec4(ldr, color.a);
|
||||
}
|
||||
@ -99,7 +99,7 @@ vec3 ComputePBR()
|
||||
vec3 N = normalize(fragNormal);
|
||||
if (useTexNormal == 1)
|
||||
{
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = normalize(N*2.0 - 1.0);
|
||||
N = normalize(N*TBN);
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ vec3 ComputePBR()
|
||||
vec3 N = normalize(fragNormal);
|
||||
if (useTexNormal == 1)
|
||||
{
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = normalize(N*2.0 - 1.0);
|
||||
N = normalize(N*TBN);
|
||||
}
|
||||
|
||||
44
examples/shaders/resources/shaders/glsl330/lights_bloom.fs
Normal file
@ -0,0 +1,44 @@
|
||||
#version 330
|
||||
|
||||
// Input values from vertex shader
|
||||
in vec3 fragPosition;
|
||||
in vec3 fragNormal;
|
||||
in vec2 fragTexCoord;
|
||||
|
||||
out vec4 finalColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec3 viewPos;
|
||||
uniform vec3 lightPositions[8];
|
||||
uniform vec3 lightColors[8];
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texColor = texture(texture0, fragTexCoord);
|
||||
vec3 norm = normalize(fragNormal);
|
||||
vec3 viewDir = normalize(viewPos - fragPosition);
|
||||
|
||||
vec3 ambient = 0.05*texColor.rgb;
|
||||
vec3 totalDiffuse = vec3(0.0);
|
||||
vec3 totalSpecular = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
vec3 lightDir = normalize(lightPositions[i] - fragPosition);
|
||||
float dist = length(lightPositions[i] - fragPosition);
|
||||
float attenuation = 1.0/(1.0 + 0.8*dist + 0.4*dist*dist);
|
||||
|
||||
// Diffuse shading
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
totalDiffuse += diff*lightColors[i]*attenuation*1.2;
|
||||
|
||||
// Blinn-Phong specular
|
||||
vec3 halfwayDir = normalize(lightDir + viewDir);
|
||||
float spec = pow(max(dot(norm, halfwayDir), 0.0), 32.0);
|
||||
totalSpecular += spec*lightColors[i]*attenuation*0.8;
|
||||
}
|
||||
|
||||
vec3 result = ambient + (totalDiffuse*texColor.rgb) + totalSpecular;
|
||||
finalColor = vec4(result, texColor.a);
|
||||
}
|
||||
23
examples/shaders/resources/shaders/glsl330/lights_bloom.vs
Normal file
@ -0,0 +1,23 @@
|
||||
#version 330
|
||||
|
||||
// Input vertex attributes
|
||||
in vec3 vertexPosition;
|
||||
in vec2 vertexTexCoord;
|
||||
in vec3 vertexNormal;
|
||||
|
||||
// Output values to fragment shader
|
||||
out vec3 fragPosition;
|
||||
out vec3 fragNormal;
|
||||
out vec2 fragTexCoord;
|
||||
|
||||
// Input uniform values
|
||||
uniform mat4 mvp;
|
||||
uniform mat4 matModel;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||
fragNormal = normalize(vec3(matModel*vec4(vertexNormal, 0.0)));
|
||||
fragTexCoord = vertexTexCoord;
|
||||
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#version 330
|
||||
|
||||
in vec2 fragTexCoord;
|
||||
out vec4 finalColor;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture(texture0, fragTexCoord);
|
||||
|
||||
// High-pass threshold blur: only pixels brighter than 0.75 in any channel contribute
|
||||
vec4 bloom = vec4(0.0);
|
||||
vec2 texel = vec2(1.0/1280.0, 1.0/720.0)*2.5;
|
||||
|
||||
for (int x = -2; x <= 2; x++)
|
||||
{
|
||||
for (int y = -2; y <= 2; y++)
|
||||
{
|
||||
vec4 smp = texture(texture0, fragTexCoord + vec2(float(x), float(y))*texel);
|
||||
float brightness = max(smp.r, max(smp.g, smp.b));
|
||||
if (brightness > 0.75) bloom += smp;
|
||||
}
|
||||
}
|
||||
bloom /= 25.0;
|
||||
|
||||
// Combine original with the bloom glow, then Reinhard tone-map back to [0, 1]
|
||||
vec3 hdr = color.rgb + bloom.rgb*1.2;
|
||||
vec3 ldr = hdr/(hdr + vec3(1.0));
|
||||
|
||||
finalColor = vec4(ldr, color.a);
|
||||
}
|
||||
@ -100,7 +100,7 @@ vec3 ComputePBR()
|
||||
vec3 N = normalize(fragNormal);
|
||||
if (useTexNormal == 1)
|
||||
{
|
||||
N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb;
|
||||
N = normalize(N*2.0 - 1.0);
|
||||
N = normalize(N*TBN);
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
*
|
||||
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3)
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Gleb A (@ggrizzly) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
|
||||
@ -168,6 +168,7 @@ int main(void)
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadTexture(light); // Unload texture
|
||||
UnloadRenderTexture(lightmap); // Unload lightmap render texture
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
185
examples/shaders/shaders_lights_bloom.c
Normal file
@ -0,0 +1,185 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shaders] example - lights bloom
|
||||
*
|
||||
* Example demonstrates forward multi-point lighting (8 point lights, attenuation and
|
||||
* Blinn-Phong specular) combined with a threshold-based bloom pass and Reinhard tone
|
||||
* mapping, applied as a full-screen post-process pass
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example uses resources/shaders/glsl100 and resources/shaders/glsl330, shared with the
|
||||
* rest of the shaders examples
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by PanicTitan (@PanicTitan) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2025 PanicTitan (@PanicTitan)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
#include "rlgl.h"
|
||||
|
||||
#include <math.h> // Required for: sinf(), cosf()
|
||||
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
#define GLSL_VERSION 330
|
||||
#else // PLATFORM_ANDROID, PLATFORM_WEB
|
||||
#define GLSL_VERSION 100
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Global Definitions
|
||||
//--------------------------------------------------------------------------------------
|
||||
#define MAX_LIGHTS 8
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT);
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - lights bloom");
|
||||
|
||||
Camera3D camera = { 0 };
|
||||
camera.position = (Vector3){ 0.0f, 5.0f, 9.0f };
|
||||
camera.target = (Vector3){ 0.0f, 0.5f, 0.0f };
|
||||
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
|
||||
camera.fovy = 45.0f;
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// Forward multi-light shader and bloom post-process shader, both loaded from the
|
||||
// resources folder shared with the rest of the shaders examples. If the GLSL version
|
||||
// guessed from the PLATFORM_DESKTOP build flag turns out to be wrong for whatever
|
||||
// raylib was built against, linking fails and silently falls back to the default
|
||||
// shader - so this retries once with the other version, and either way the result
|
||||
// is checked explicitly and reported on screen rather than staying silently wrong
|
||||
Shader lightShader = LoadShader(TextFormat("resources/shaders/glsl%i/lights_bloom.vs", GLSL_VERSION),
|
||||
TextFormat("resources/shaders/glsl%i/lights_bloom.fs", GLSL_VERSION));
|
||||
Shader bloomShader = LoadShader(0, TextFormat("resources/shaders/glsl%i/lights_bloom_post.fs", GLSL_VERSION));
|
||||
|
||||
// Load models from generated cube mesh and plane
|
||||
// NOTE: Meshes are automatically unloaded on UnloadModel()
|
||||
Model cube = LoadModelFromMesh(GenMeshCube(2.0f, 2.0f, 2.0f));
|
||||
Model floor = LoadModelFromMesh(GenMeshPlane(14.0f, 14.0f, 1, 1));
|
||||
cube.materials[0].shader = lightShader;
|
||||
floor.materials[0].shader = lightShader;
|
||||
|
||||
int lightPosLoc = GetShaderLocation(lightShader, "lightPositions");
|
||||
int lightColLoc = GetShaderLocation(lightShader, "lightColors");
|
||||
int viewPosLoc = GetShaderLocation(lightShader, "viewPos");
|
||||
|
||||
Vector3 lightPositions[MAX_LIGHTS] = { 0 };
|
||||
Vector3 lightColors[MAX_LIGHTS] = {
|
||||
{ 1.0f, 0.2f, 0.2f }, // Red
|
||||
{ 0.2f, 1.0f, 0.3f }, // Green
|
||||
{ 0.2f, 0.5f, 1.0f }, // Blue
|
||||
{ 1.0f, 0.8f, 0.1f }, // Yellow
|
||||
{ 1.0f, 0.1f, 0.8f }, // Magenta
|
||||
{ 0.1f, 1.0f, 1.0f }, // Cyan
|
||||
{ 1.0f, 0.4f, 0.1f }, // Orange
|
||||
{ 0.7f, 0.2f, 1.0f }, // Purple
|
||||
};
|
||||
|
||||
SetShaderValueV(lightShader, lightColLoc, lightColors, SHADER_UNIFORM_VEC3, MAX_LIGHTS);
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
UpdateCamera(&camera, CAMERA_ORBITAL);
|
||||
|
||||
float time = (float)GetTime();
|
||||
|
||||
// Orbital path for each point light, its own radius/height offset by index
|
||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||
{
|
||||
float angle = (i/(float)MAX_LIGHTS)*2.0f*PI + time*0.6f;
|
||||
float radius = 4.2f + sinf(time*1.2f + i)*0.4f;
|
||||
float height = 1.0f + sinf(time*1.8f + i)*0.6f;
|
||||
|
||||
lightPositions[i] = (Vector3){ sinf(angle)*radius, height, cosf(angle)*radius };
|
||||
}
|
||||
|
||||
SetShaderValueV(lightShader, lightPosLoc, lightPositions, SHADER_UNIFORM_VEC3, MAX_LIGHTS);
|
||||
SetShaderValue(lightShader, viewPosLoc, &camera.position, SHADER_UNIFORM_VEC3);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
// Render the lit scene to an offscreen texture
|
||||
BeginTextureMode(target);
|
||||
|
||||
ClearBackground((Color){ 12, 12, 18, 255 });
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
DrawModel(cube, (Vector3){ 0.0f, 1.0f, 0.0f }, 1.0f, GRAY);
|
||||
DrawModel(floor, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, DARKGRAY);
|
||||
DrawGrid(10, 1.0f);
|
||||
|
||||
// Glowing bulbs mark each light's position
|
||||
for (int i = 0; i < MAX_LIGHTS; i++)
|
||||
{
|
||||
Color bulbColor = (Color){
|
||||
(unsigned char)(lightColors[i].x*255),
|
||||
(unsigned char)(lightColors[i].y*255),
|
||||
(unsigned char)(lightColors[i].z*255),
|
||||
255 };
|
||||
|
||||
DrawSphere(lightPositions[i], 0.15f, bulbColor);
|
||||
}
|
||||
|
||||
EndMode3D();
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
// Present the offscreen texture through the bloom + tone mapping shader
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(BLACK);
|
||||
|
||||
Rectangle srcRec = { 0, 0, (float)target.texture.width, (float)-target.texture.height };
|
||||
|
||||
BeginShaderMode(bloomShader);
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(target.texture, srcRec, (Vector2){ 0, 0 }, WHITE);
|
||||
EndShaderMode();
|
||||
|
||||
DrawText("BALANCED MULTI-LIGHT + REINHARD TONE MAPPED BLOOM", 20, 20, 20, GREEN);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModel(cube);
|
||||
UnloadModel(floor);
|
||||
UnloadShader(lightShader);
|
||||
UnloadShader(bloomShader);
|
||||
UnloadRenderTexture(target);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
examples/shaders/shaders_lights_bloom.png
Normal file
|
After Width: | Height: | Size: 203 KiB |
@ -139,6 +139,9 @@ int main(void)
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
RL_FREE(transforms); // Free transforms
|
||||
UnloadMaterial(matInstances); // Also unloads the instancing shader
|
||||
UnloadMaterial(matDefault); // Unload default material
|
||||
UnloadMesh(cube); // Unload cube mesh
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
@ -91,6 +91,8 @@ int main(void)
|
||||
Image whiteImage = GenImageColor(GOL_WIDTH, GOL_WIDTH, WHITE);
|
||||
Texture whiteTex = LoadTextureFromImage(whiteImage);
|
||||
UnloadImage(whiteImage);
|
||||
|
||||
SetTargetFPS(0); // Set our game to run with an uncapped framerate
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
|
||||
@ -68,7 +68,7 @@ int main(void)
|
||||
SetShaderValue(shadowShader, lightDirLoc, &lightDir, SHADER_UNIFORM_VEC3);
|
||||
SetShaderValue(shadowShader, lightColLoc, &lightColorNormalized, SHADER_UNIFORM_VEC4);
|
||||
int ambientLoc = GetShaderLocation(shadowShader, "ambient");
|
||||
float ambient[4] = {0.1f, 0.1f, 0.1f, 1.0f};
|
||||
float ambient[4] = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||
SetShaderValue(shadowShader, ambientLoc, ambient, SHADER_UNIFORM_VEC4);
|
||||
int lightVPLoc = GetShaderLocation(shadowShader, "lightVP");
|
||||
int shadowMapLoc = GetShaderLocation(shadowShader, "shadowMap");
|
||||
@ -81,7 +81,7 @@ int main(void)
|
||||
for (int i = 0; i < robot.materialCount; i++) robot.materials[i].shader = shadowShader;
|
||||
|
||||
int animCount = 0;
|
||||
ModelAnimation *anims = LoadModelAnimations("resources/models/robot.glb", &animCount);
|
||||
ModelAnimation* anims = LoadModelAnimations("resources/models/robot.glb", &animCount);
|
||||
|
||||
RenderTexture2D shadowMap = LoadShadowmapRenderTexture(SHADOWMAP_RESOLUTION, SHADOWMAP_RESOLUTION);
|
||||
|
||||
@ -111,9 +111,11 @@ int main(void)
|
||||
//----------------------------------------------------------------------------------
|
||||
float deltaTime = GetFrameTime();
|
||||
|
||||
UpdateCamera(&camera, CAMERA_ORBITAL);
|
||||
|
||||
// send the updated camera position to the shader so that it can calculate the correct lighting for the scene
|
||||
Vector3 cameraPos = camera.position;
|
||||
SetShaderValue(shadowShader, shadowShader.locs[SHADER_LOC_VECTOR_VIEW], &cameraPos, SHADER_UNIFORM_VEC3);
|
||||
UpdateCamera(&camera, CAMERA_ORBITAL);
|
||||
|
||||
frameCounter++;
|
||||
frameCounter %= (anims[0].keyframeCount);
|
||||
@ -160,6 +162,7 @@ int main(void)
|
||||
EndMode3D();
|
||||
|
||||
EndTextureMode();
|
||||
|
||||
lightViewProj = MatrixMultiply(lightView, lightProj);
|
||||
|
||||
// PASS 02: Draw the scene into main framebuffer, using the generated shadowmap
|
||||
@ -177,6 +180,9 @@ int main(void)
|
||||
DrawScene(cube, robot); // Draw the same exact things as we drew in the shadowmap!
|
||||
EndMode3D();
|
||||
|
||||
rlActiveTextureSlot(textureActiveSlot);
|
||||
rlDisableTexture();
|
||||
|
||||
DrawText("Use the arrow keys to rotate the light!", 10, 10, 30, RED);
|
||||
DrawText("Shadows in raylib using the shadowmapping algorithm!", screenWidth - 280, screenHeight - 20, 10, GRAY);
|
||||
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
#include <stdlib.h> // Required for: malloc(), free()
|
||||
#include <math.h> // Required for: hypot()
|
||||
|
||||
@ -68,6 +70,8 @@ int main(void)
|
||||
Vector2 pressOffset = { 0 }; // Mouse press offset relative to the ball that grabbedd
|
||||
|
||||
float gravity = 100; // World gravity
|
||||
|
||||
Vector2 windowPosition = GetWindowPosition();
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//---------------------------------------------------------------------------------------
|
||||
@ -128,6 +132,17 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Get window position change for shaking
|
||||
Vector2 windowPositionDelta = Vector2Subtract(windowPosition, GetWindowPosition());
|
||||
|
||||
if (Vector2Length(windowPositionDelta) > 5.0f)
|
||||
{
|
||||
for (int i = 0; i < ballCount; i++)
|
||||
{
|
||||
if (!balls[i].grabbed) balls[i].speed = Vector2Add(balls[i].speed, Vector2Scale(windowPositionDelta, 10.0f));
|
||||
}
|
||||
}
|
||||
|
||||
// Shake balls
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE))
|
||||
{
|
||||
@ -194,6 +209,8 @@ int main(void)
|
||||
ball->prevPosition = ball->position;
|
||||
}
|
||||
}
|
||||
|
||||
windowPosition = GetWindowPosition();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
@ -222,8 +239,9 @@ int main(void)
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
RL_FREE(balls);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
164
examples/shapes/shapes_drag_puzzle.c
Normal file
@ -0,0 +1,164 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - drag puzzle
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Gabriel Piangers (@gabriel-piangers) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2026 Gabriel Piangers (@gabriel-piangers)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "raymath.h"
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Vector2 center;
|
||||
float radius;
|
||||
} Circle;
|
||||
|
||||
typedef struct {
|
||||
Vector2 v1;
|
||||
Vector2 v2;
|
||||
Vector2 v3;
|
||||
} Triangle;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - drag puzzle");
|
||||
|
||||
// Rectangle
|
||||
Rectangle rec = { screenWidth/2 - 250, screenHeight/2 + 50, 100.0f, 100.0f };
|
||||
Rectangle recArea = { screenWidth/2 - 60, screenHeight/2 - 110, 110.0f, 110.0f };
|
||||
bool recPickedUp = false;
|
||||
|
||||
// Circle
|
||||
Circle circ = { screenWidth/2, screenHeight/2 + 100, 50.0f };
|
||||
Circle circArea = { screenWidth/2 - 195, screenHeight/2 - 55, 55.0f };
|
||||
bool circPickedUp = false;
|
||||
|
||||
// Triangle
|
||||
Triangle tri = { { 600, 282 }, { 550, 369 }, { 650, 369 } };
|
||||
Triangle triArea = { { 600, 115 }, { 540, 222 }, { 660, 222 } };
|
||||
bool triPickedUp = false;
|
||||
|
||||
Vector2 mouseOffset = { 0.0f, 0.0f }; // Stores the offset of the mouse relative to the object's pivot point
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
Vector2 mousePosition = GetMousePosition();
|
||||
bool recPlaced = false;
|
||||
bool circPlaced = false;
|
||||
bool triPlaced = false;
|
||||
|
||||
// Detect object pickup input
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosition, rec))
|
||||
{
|
||||
recPickedUp = true;
|
||||
mouseOffset = (Vector2) { rec.x - mousePosition.x, rec.y - mousePosition.y };
|
||||
}
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointCircle(mousePosition, circ.center, circ.radius))
|
||||
{
|
||||
circPickedUp = true;
|
||||
mouseOffset = (Vector2) { circ.center.x - mousePosition.x, circ.center.y - mousePosition.y };
|
||||
}
|
||||
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointTriangle(mousePosition, tri.v1, tri.v2, tri.v3))
|
||||
{
|
||||
triPickedUp = true;
|
||||
mouseOffset = (Vector2) { tri.v1.x - mousePosition.x, tri.v1.y - mousePosition.y }; // Uses v1 as the pivot point
|
||||
}
|
||||
|
||||
// Detect object drop input
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && recPickedUp) recPickedUp = false;
|
||||
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && circPickedUp) circPickedUp = false;
|
||||
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && triPickedUp) triPickedUp = false;
|
||||
|
||||
// Rectangle update
|
||||
if (recPickedUp)
|
||||
{
|
||||
rec.x = mousePosition.x + mouseOffset.x;
|
||||
rec.y = mousePosition.y + mouseOffset.y;
|
||||
}
|
||||
Rectangle RecCol = GetCollisionRec(recArea, rec);
|
||||
if (RecCol.width == rec.width && RecCol.height == rec.height) recPlaced = true;
|
||||
|
||||
// Circle update
|
||||
if (circPickedUp)
|
||||
{
|
||||
circ.center.x = mousePosition.x + mouseOffset.x;
|
||||
circ.center.y = mousePosition.y + mouseOffset.y;
|
||||
}
|
||||
if (Vector2Distance(circ.center, circArea.center) < circArea.radius - circ.radius) circPlaced = true;
|
||||
|
||||
// Triangle update
|
||||
if (triPickedUp)
|
||||
{
|
||||
Vector2 v2Offset = { tri.v2.x - tri.v1.x, tri.v2.y - tri.v1.y };
|
||||
Vector2 v3Offset = { tri.v3.x - tri.v1.x, tri.v3.y - tri.v1.y };
|
||||
|
||||
tri.v1 = (Vector2) { mousePosition.x + mouseOffset.x, mousePosition.y + mouseOffset.y };
|
||||
tri.v2 = (Vector2) { tri.v1.x + v2Offset.x, tri.v1.y + v2Offset.y };
|
||||
tri.v3 = (Vector2) { tri.v1.x + v3Offset.x, tri.v1.y + v3Offset.y };
|
||||
}
|
||||
if (
|
||||
CheckCollisionPointTriangle(tri.v1, triArea.v1, triArea.v2, triArea.v3) &&
|
||||
CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3) &&
|
||||
CheckCollisionPointTriangle(tri.v2, triArea.v1, triArea.v2, triArea.v3)
|
||||
) triPlaced = true;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawRectangleLinesEx(recArea, 2.0f, recPlaced ? GREEN : RED);
|
||||
DrawCircleLinesEx(circArea.center, circArea.radius, 2.0f, circPlaced ? GREEN : RED);
|
||||
DrawTriangleLinesEx(triArea.v1, triArea.v2, triArea.v3, 2.0f, triPlaced ? GREEN : RED);
|
||||
|
||||
// Draws objects that are not picked up first
|
||||
if (!triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
|
||||
if (!circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
|
||||
if (!recPickedUp) DrawRectangleRec(rec, ORANGE);
|
||||
|
||||
// Draws the object that is being dragged on top of others
|
||||
if (triPickedUp) DrawTriangle(tri.v1, tri.v2, tri.v3, VIOLET);
|
||||
if (circPickedUp) DrawCircleV(circ.center, circ.radius, BLUE);
|
||||
if (recPickedUp) DrawRectangleRec(rec, ORANGE);
|
||||
|
||||
DrawText("Use mouse to drag and drop the objects into the right spot!", 10, 10, 20, GRAY);
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
examples/shapes/shapes_drag_puzzle.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
@ -59,7 +59,7 @@ int main(void)
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - collision ellipses");
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - ellipse collision");
|
||||
SetTargetFPS(60);
|
||||
|
||||
Vector2 ellipseACenter = { (float)screenWidth/4, (float)screenHeight/2 };
|
||||
|
||||
@ -56,7 +56,7 @@ int main(void)
|
||||
Vector2 mousePos = { 0 };
|
||||
Vector2 prevMousePos = { 0 };
|
||||
Vector2 scaleVector = { 1.0f, -1.0f };
|
||||
Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
|
||||
Vector2 offset = { GetRenderWidth()/2.0f, GetRenderHeight()/2.0f };
|
||||
|
||||
Camera2D camera = { 0 };
|
||||
camera.target = (Vector2){ 0 };
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 5.6
|
||||
* Example originally created with raylib 5.6, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Balamurugan R (@Bala050814]) and reviewed by Ramon Santamaria (@raysan5)
|
||||
* Example contributed by Balamurugan R (@Bala050814) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
|
||||
407
examples/shapes/shapes_outlines_testbed.c
Normal file
@ -0,0 +1,407 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - outlines testbed
|
||||
*
|
||||
* Example complexity rating: [★★★☆] 3/4
|
||||
*
|
||||
* Example originally created with raylib 6.1, last time updated with raylib 6.1
|
||||
*
|
||||
* Example contributed by Matthew Roush (@MatthewRoush) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2026 Matthew Roush (@MatthewRoush)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#include "raymath.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define COLOR_FILLED DARKBLUE
|
||||
#define COLOR_OUTLINE YELLOW
|
||||
|
||||
#define SHAPE_SPACING 14.0f
|
||||
#define SHAPE_SIZE 46.0f
|
||||
#define BOX_SPACING 10.0f
|
||||
|
||||
#define MOUSE_CAMERA_ZOOM_SPEED 0.3f
|
||||
#define KEYBOARD_CAMERA_MOVE_SPEED 10.0f
|
||||
#define KEYBOARD_CAMERA_ZOOM_SPEED 0.1f
|
||||
|
||||
#define CAMERA_ZOOM_MIN 0.1f
|
||||
#define CAMERA_ZOOM_MAX 1000.0f
|
||||
|
||||
// The shapes are ordered according to their order in this enum, left to right
|
||||
enum {
|
||||
ORDER_RECTANGLE = 0,
|
||||
ORDER_RECTANGLE_ROUNDED,
|
||||
ORDER_CIRCLE,
|
||||
ORDER_ELLIPSE,
|
||||
ORDER_CIRCLE_SECTOR,
|
||||
ORDER_RING,
|
||||
ORDER_TRIANGLE,
|
||||
ORDER_POLYGON,
|
||||
COUNT_SHAPES
|
||||
};
|
||||
|
||||
// The line style groups are ordered according to their order in this enum, top to bottom
|
||||
enum {
|
||||
ORDER_LINES = 0,
|
||||
ORDER_LINES_EX_WORLD,
|
||||
ORDER_LINES_EX_SCREEN,
|
||||
};
|
||||
|
||||
#define BOX_WIDTH (SHAPE_SIZE*COUNT_SHAPES + SHAPE_SPACING*(COUNT_SHAPES - 1) + BOX_SPACING*2.0f)
|
||||
#define BOX_HEIGHT (SHAPE_SIZE + BOX_SPACING*2.0f)
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - outlines testbed");
|
||||
|
||||
Camera2D camera = { .zoom = 1 };
|
||||
|
||||
// User configurable options while running the program.
|
||||
float lineOpacity = 130;
|
||||
float lineThickness = 4.0f;
|
||||
float rectangleRoundness = 0.4f;
|
||||
float rectangleSegments = 9;
|
||||
float ellipseRadiusY = 0.5f;
|
||||
float circleStartAngle = 20.0f;
|
||||
float circleEndAngle = 270.0f;
|
||||
float circleSegments = 36;
|
||||
float ringInnerRadiusScale = 0.3f;
|
||||
float polygonSides = 6;
|
||||
|
||||
bool disableMouseControl = false;
|
||||
|
||||
const Rectangle optionsBackground = { 510, 0, 290, 450 };
|
||||
|
||||
const Vector2 zoomPoint = {((float)screenWidth - optionsBackground.width)/2.0f, (float)screenHeight/2.0f};
|
||||
|
||||
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(WHITE));
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
const Vector2 mousePosScreen = GetMousePosition();
|
||||
const Vector2 mouseWheelVec = GetMouseWheelMoveV();
|
||||
|
||||
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mousePosScreen, optionsBackground)) disableMouseControl = true;
|
||||
|
||||
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) disableMouseControl = false;
|
||||
|
||||
if (!disableMouseControl) {
|
||||
if (mouseWheelVec.y != 0.0f) {
|
||||
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
|
||||
camera.zoom *= exp2f(MOUSE_CAMERA_ZOOM_SPEED*mouseWheelVec.y); // Constant zoom rate
|
||||
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
|
||||
|
||||
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
|
||||
}
|
||||
|
||||
if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
|
||||
const Vector2 mouseDelta = GetMouseDelta();
|
||||
camera.target.x -= mouseDelta.x/camera.zoom;
|
||||
camera.target.y -= mouseDelta.y/camera.zoom;
|
||||
|
||||
const int mouseMaxX = (int)optionsBackground.x;
|
||||
const int mouseMaxY = screenHeight;
|
||||
|
||||
int newX = (int)mousePosScreen.x;
|
||||
int newY = (int)mousePosScreen.y;
|
||||
|
||||
// In C, the '%' operator computes the remainder, we want the modulus
|
||||
newX = (newX%mouseMaxX + mouseMaxX)%mouseMaxX;
|
||||
newY = (newY%mouseMaxY + mouseMaxY)%mouseMaxY;
|
||||
|
||||
if ((newX != (int)mousePosScreen.x) || (newY != (int)mousePosScreen.y)) SetMousePosition(newX, newY);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyDown(KEY_A)) camera.target.x -= KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
|
||||
if (IsKeyDown(KEY_D)) camera.target.x += KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
|
||||
if (IsKeyDown(KEY_W)) camera.target.y -= KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
|
||||
if (IsKeyDown(KEY_S)) camera.target.y += KEYBOARD_CAMERA_MOVE_SPEED/camera.zoom;
|
||||
|
||||
if (IsKeyDown(KEY_UP))
|
||||
{
|
||||
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
|
||||
camera.zoom *= exp2f(KEYBOARD_CAMERA_ZOOM_SPEED);
|
||||
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
|
||||
|
||||
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
|
||||
}
|
||||
if (IsKeyDown(KEY_DOWN))
|
||||
{
|
||||
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
|
||||
camera.zoom *= exp2f(-KEYBOARD_CAMERA_ZOOM_SPEED);
|
||||
camera.zoom = Clamp(camera.zoom, CAMERA_ZOOM_MIN, CAMERA_ZOOM_MAX);
|
||||
|
||||
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_Z))
|
||||
{
|
||||
const Vector2 zoomPoint = {((float)screenWidth - optionsBackground.width)/2.0f, (float)screenHeight/2.0f};
|
||||
const Vector2 prevWorldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
|
||||
camera.zoom = 1.0f;
|
||||
|
||||
const Vector2 worldZoomPoint = GetScreenToWorld2D(zoomPoint, camera);
|
||||
camera.target = Vector2Add(camera.target, Vector2Subtract(prevWorldZoomPoint, worldZoomPoint));
|
||||
}
|
||||
|
||||
if (IsKeyPressed(KEY_C)) camera.target = (Vector2){ 0 };
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground((Color){ 50, 50, 55, 255 });
|
||||
|
||||
Color colorOutline = COLOR_OUTLINE;
|
||||
colorOutline.a = (unsigned char)lineOpacity;
|
||||
|
||||
BeginMode2D(camera);
|
||||
|
||||
const float shapeOffset = BOX_SPACING*2.0f;
|
||||
const float shapePaddingX = SHAPE_SIZE + SHAPE_SPACING;
|
||||
const float shapePaddingY = SHAPE_SIZE + SHAPE_SPACING + BOX_SPACING*2.0f;
|
||||
|
||||
const float radiusX = SHAPE_SIZE/2.0f;
|
||||
const float radiusY = radiusX*ellipseRadiusY;
|
||||
|
||||
const float ringOuterRadius = SHAPE_SIZE/2.0f;
|
||||
const float ringInnerRadius = ringOuterRadius*ringInnerRadiusScale;
|
||||
|
||||
const Vector2 triangleVertex0Offset = { 0.0f, SHAPE_SIZE*0.8f };
|
||||
const Vector2 triangleVertex1Offset = { SHAPE_SIZE*0.6f, SHAPE_SIZE };
|
||||
const Vector2 triangleVertex2Offset = { SHAPE_SIZE, 0.0f };
|
||||
|
||||
// ----------------------------------------
|
||||
// Draw*Lines()
|
||||
float posY = shapeOffset + shapePaddingY*ORDER_LINES;
|
||||
|
||||
// Rectangle
|
||||
float posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
|
||||
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
|
||||
DrawRectangleLines(posX, posY, SHAPE_SIZE, SHAPE_SIZE, colorOutline);
|
||||
|
||||
// Rectangle Rounded
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
|
||||
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
|
||||
DrawRectangleRoundedLines((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, colorOutline);
|
||||
|
||||
// Circle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
|
||||
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
|
||||
DrawCircleLinesV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, colorOutline);
|
||||
|
||||
// Ellipse
|
||||
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
|
||||
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
|
||||
DrawEllipseLinesV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, colorOutline);
|
||||
|
||||
// Circle Sector
|
||||
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
|
||||
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
|
||||
DrawCircleSectorLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, colorOutline);
|
||||
|
||||
// Ring
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RING;
|
||||
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
|
||||
DrawRingLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, colorOutline);
|
||||
|
||||
// Triangle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
|
||||
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
|
||||
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
|
||||
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
|
||||
COLOR_FILLED);
|
||||
DrawTriangleLines((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
|
||||
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
|
||||
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
|
||||
colorOutline);
|
||||
|
||||
// Polygon
|
||||
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
|
||||
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
|
||||
DrawPolyLines((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, colorOutline);
|
||||
|
||||
// Group the shapes
|
||||
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*Lines()");
|
||||
// ----------------------------------------
|
||||
|
||||
// ----------------------------------------
|
||||
// Draw*LinesEx() with world space pixel thickness
|
||||
posY = shapeOffset + shapePaddingY*ORDER_LINES_EX_WORLD;
|
||||
|
||||
// Rectangle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
|
||||
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
|
||||
DrawRectangleLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, lineThickness, colorOutline);
|
||||
|
||||
// Rectangle Rounded
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
|
||||
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
|
||||
DrawRectangleRoundedLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, lineThickness, colorOutline);
|
||||
|
||||
// Circle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
|
||||
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
|
||||
DrawCircleLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, lineThickness, colorOutline);
|
||||
|
||||
// Ellipse
|
||||
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
|
||||
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
|
||||
DrawEllipseLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, lineThickness, colorOutline);
|
||||
|
||||
// Circle Sector
|
||||
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
|
||||
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
|
||||
DrawCircleSectorLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, lineThickness, colorOutline);
|
||||
|
||||
// Ring
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RING;
|
||||
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
|
||||
DrawRingLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, lineThickness, colorOutline);
|
||||
|
||||
// Triangle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
|
||||
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
|
||||
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
|
||||
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
|
||||
COLOR_FILLED);
|
||||
DrawTriangleLinesEx((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
|
||||
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
|
||||
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
|
||||
lineThickness, colorOutline);
|
||||
|
||||
// Polygon
|
||||
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
|
||||
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
|
||||
DrawPolyLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, lineThickness, colorOutline);
|
||||
|
||||
// Group the shapes
|
||||
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*LinesEx() with *world space* pixel thickness");
|
||||
// ----------------------------------------
|
||||
|
||||
// ----------------------------------------
|
||||
// Draw*LinesEx() with screen space pixel thickness
|
||||
posY = shapeOffset + shapePaddingY*ORDER_LINES_EX_SCREEN;
|
||||
|
||||
float constantThickness = lineThickness/camera.zoom;
|
||||
|
||||
// Rectangle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE;
|
||||
DrawRectangleRec((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, COLOR_FILLED);
|
||||
DrawRectangleLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, constantThickness, colorOutline);
|
||||
|
||||
// Rectangle Rounded
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RECTANGLE_ROUNDED;
|
||||
DrawRectangleRounded((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, COLOR_FILLED);
|
||||
DrawRectangleRoundedLinesEx((Rectangle){ posX, posY, SHAPE_SIZE, SHAPE_SIZE }, rectangleRoundness, (int)rectangleSegments, constantThickness, colorOutline);
|
||||
|
||||
// Circle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE;
|
||||
DrawCircleV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, COLOR_FILLED);
|
||||
DrawCircleLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, constantThickness, colorOutline);
|
||||
|
||||
// Ellipse
|
||||
posX = shapeOffset + shapePaddingX*ORDER_ELLIPSE;
|
||||
DrawEllipseV((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, COLOR_FILLED);
|
||||
DrawEllipseLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, radiusY, constantThickness, colorOutline);
|
||||
|
||||
// Circle Sector
|
||||
posX = shapeOffset + shapePaddingX*ORDER_CIRCLE_SECTOR;
|
||||
DrawCircleSector((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
|
||||
DrawCircleSectorLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, radiusX, circleStartAngle, circleEndAngle, (int)circleSegments, constantThickness, colorOutline);
|
||||
|
||||
// Ring
|
||||
posX = shapeOffset + shapePaddingX*ORDER_RING;
|
||||
DrawRing((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, COLOR_FILLED);
|
||||
DrawRingLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, ringInnerRadius, ringOuterRadius, circleStartAngle, circleEndAngle, (int)circleSegments, constantThickness, colorOutline);
|
||||
|
||||
// Triangle
|
||||
posX = shapeOffset + shapePaddingX*ORDER_TRIANGLE;
|
||||
DrawTriangle((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
|
||||
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
|
||||
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
|
||||
COLOR_FILLED);
|
||||
DrawTriangleLinesEx((Vector2){ posX + triangleVertex0Offset.x, posY + triangleVertex0Offset.y },
|
||||
(Vector2){ posX + triangleVertex1Offset.x, posY + triangleVertex1Offset.y },
|
||||
(Vector2){ posX + triangleVertex2Offset.x, posY + triangleVertex2Offset.y },
|
||||
constantThickness, colorOutline);
|
||||
|
||||
// Polygon
|
||||
posX = shapeOffset + shapePaddingX*ORDER_POLYGON;
|
||||
DrawPoly((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, COLOR_FILLED);
|
||||
DrawPolyLinesEx((Vector2){ posX + SHAPE_SIZE/2.0f, posY + SHAPE_SIZE/2.0f }, (int)polygonSides, radiusX, 0.0f, constantThickness, colorOutline);
|
||||
|
||||
// Group the shapes
|
||||
GuiGroupBox((Rectangle){ shapeOffset - BOX_SPACING, posY - BOX_SPACING, BOX_WIDTH, BOX_HEIGHT }, "Draw*LinesEx() with *screen space* pixel thickness");
|
||||
// ----------------------------------------
|
||||
|
||||
EndMode2D();
|
||||
|
||||
DrawRectangleRec(optionsBackground, Fade(DARKGRAY, 0.75f));
|
||||
|
||||
DrawRectangleRec((Rectangle){ optionsBackground.x, 360, optionsBackground.width, 90 }, Fade(BLACK, 0.4f));
|
||||
DrawLineEx((Vector2){ optionsBackground.x, 360 }, (Vector2){ optionsBackground.x + optionsBackground.width, 360 }, 1.0f, BLACK);
|
||||
|
||||
DrawText("Move with the mouse or WASD keys", (int)optionsBackground.x + 10, 370, 10, ORANGE);
|
||||
DrawText("Zoom with the mouse or UP and DOWN keys", (int)optionsBackground.x + 10, 390, 10, ORANGE);
|
||||
DrawText("Press C to reset position", (int)optionsBackground.x + 10, 410, 10, ORANGE);
|
||||
DrawText("Press Z to reset zoom", (int)optionsBackground.x + 10, 430, 10, ORANGE);
|
||||
|
||||
DrawLineEx((Vector2){ optionsBackground.x, optionsBackground.y }, (Vector2){ optionsBackground.x, optionsBackground.y + optionsBackground.height }, 1.0f, BLACK);
|
||||
|
||||
GuiSliderBar((Rectangle){ 605, 10, 150, 25 }, "Line Opacity" , TextFormat("%d" , (int)lineOpacity) , &lineOpacity , 0 , 255);
|
||||
GuiSliderBar((Rectangle){ 605, 45, 150, 25 }, "Thickness" , TextFormat("%.2f", lineThickness) , &lineThickness , -20.0f , 40.0f);
|
||||
GuiSliderBar((Rectangle){ 605, 80, 150, 25 }, "Rect Roundness" , TextFormat("%.2f", rectangleRoundness) , &rectangleRoundness , -1.0f , 2.0f);
|
||||
GuiSliderBar((Rectangle){ 605, 115, 150, 25 }, "Rect Segments" , TextFormat("%d" , (int)rectangleSegments), &rectangleSegments , -1 , 100);
|
||||
GuiSliderBar((Rectangle){ 605, 150, 150, 25 }, "Ellipse Radius Y", TextFormat("%.2f", ellipseRadiusY) , &ellipseRadiusY , 0.0f , 1.25f);
|
||||
GuiSliderBar((Rectangle){ 605, 185, 150, 25 }, "Start Angle" , TextFormat("%.2f", circleStartAngle) , &circleStartAngle , -360.0f, 360.0f);
|
||||
GuiSliderBar((Rectangle){ 605, 220, 150, 25 }, "End Angle" , TextFormat("%.2f", circleEndAngle) , &circleEndAngle , -360.0f, 360.0f);
|
||||
GuiSliderBar((Rectangle){ 605, 255, 150, 25 }, "Circle Segments" , TextFormat("%d" , (int)circleSegments) , &circleSegments , -1 , 100);
|
||||
GuiSliderBar((Rectangle){ 605, 290, 150, 25 }, "Ring Radius" , TextFormat("%.2f", ringInnerRadiusScale) , &ringInnerRadiusScale, -1.0f , 2.0f);
|
||||
GuiSliderBar((Rectangle){ 605, 325, 150, 25 }, "Poly Sides" , TextFormat("%d" , (int)polygonSides) , &polygonSides , -1 , 100);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
examples/shapes/shapes_outlines_testbed.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
78
examples/shapes/shapes_outlines_thickness.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - outlines thickness
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.1, last time updated with raylib 6.1
|
||||
*
|
||||
* Example contributed by Matthew Roush (@MatthewRoush) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2026 Matthew Roush (@MatthewRoush)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h" // Required for GUI controls
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - outlines thickness");
|
||||
|
||||
float thick = 5.0f;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update variables / Implement example logic at this point
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
GuiSliderBar((Rectangle){ 290, 50, 220, 24 }, "Thickness", TextFormat("%.2f", thick), &thick, -30.0f, 30.0f);
|
||||
|
||||
DrawRectangle(35, 180, 220, 220, LIGHTGRAY);
|
||||
DrawRectangleLinesEx((Rectangle){ 35, 180, 220, 220 }, thick, BLUE);
|
||||
DrawText("DrawRectangleLinesEx()", 35, 160, 10, BLACK);
|
||||
|
||||
DrawRectangleRounded((Rectangle){ 290, 180, 220, 220 }, 0.2f, 9, LIGHTGRAY);
|
||||
DrawRectangleRoundedLinesEx((Rectangle){ 290, 180, 220, 220 }, 0.2f, 9, thick, BLUE);
|
||||
DrawText("DrawRectangleRoundedLinesEx()", 290, 160, 10, BLACK);
|
||||
|
||||
DrawCircle(655, 290, 110, LIGHTGRAY);
|
||||
DrawCircleLinesEx((Vector2){ 655, 290 }, 110, thick, BLUE);
|
||||
DrawText("DrawCircleLinesEx()", 545, 160, 10, BLACK);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
examples/shapes/shapes_outlines_thickness.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
@ -16,12 +16,13 @@
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_PIE_SLICES 10 // Max pie slices
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
@ -39,12 +40,8 @@ int main(void)
|
||||
int sliceCount = 7;
|
||||
float donutInnerRadius = 25.0f;
|
||||
float values[MAX_PIE_SLICES] = { 300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f }; // Initial slice values
|
||||
char labels[MAX_PIE_SLICES][32] = { 0 };
|
||||
bool editingLabel[MAX_PIE_SLICES] = { 0 };
|
||||
|
||||
for (int i = 0; i < MAX_PIE_SLICES; i++)
|
||||
snprintf(labels[i], 32, "Slice %02i", i + 1);
|
||||
|
||||
bool showValues = true;
|
||||
bool showPercentages = false;
|
||||
bool showDonut = false;
|
||||
@ -59,7 +56,7 @@ int main(void)
|
||||
|
||||
// UI Panel top-left anchor
|
||||
const Vector2 panelPos = {
|
||||
(float)screenWidth - panelMargin - panelWidth,
|
||||
(float)screenWidth - panelMargin - panelWidth,
|
||||
(float)panelMargin
|
||||
};
|
||||
|
||||
@ -72,7 +69,7 @@ int main(void)
|
||||
|
||||
// Pie chart geometry
|
||||
const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight };
|
||||
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f};
|
||||
const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f };
|
||||
const float radius = 205.0f;
|
||||
|
||||
// Total value for percentage calculations
|
||||
@ -93,6 +90,7 @@ int main(void)
|
||||
// Check for mouse hover over slices
|
||||
hoveredSlice = -1; // Reset hovered slice
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
|
||||
if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas
|
||||
{
|
||||
float dx = mousePos.x - center.x;
|
||||
@ -176,7 +174,7 @@ int main(void)
|
||||
|
||||
if (showDonut) GuiDisable();
|
||||
GuiSliderBar((Rectangle){ panelPos.x + 80, (float)panelPos.y + 12 + 130, panelRect.width - 100, 30 },
|
||||
"Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f);
|
||||
"Inner Radius", NULL, & donutInnerRadius, 5.0f, radius - 10.0f);
|
||||
GuiEnable();
|
||||
|
||||
GuiLine((Rectangle){ panelPos.x + 10, (float)panelPos.y + 12 + 170, panelRect.width - 20, 1 }, NULL);
|
||||
@ -190,8 +188,7 @@ int main(void)
|
||||
};
|
||||
int contentHeight = sliceCount*35;
|
||||
|
||||
GuiScrollPanel(scrollPanelBounds, NULL,
|
||||
(Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
|
||||
GuiScrollPanel(scrollPanelBounds, NULL, (Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight },
|
||||
&scrollContentOffset, &view);
|
||||
|
||||
const float contentX = view.x + scrollContentOffset.x; // Left of content
|
||||
@ -208,7 +205,8 @@ int main(void)
|
||||
DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color);
|
||||
|
||||
// Label textbox
|
||||
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, labels[i], 32, editingLabel[i])) editingLabel[i] = !editingLabel[i];
|
||||
if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, TextFormat("Slice %02i", i + 1), 32, editingLabel[i]))
|
||||
editingLabel[i] = !editingLabel[i];
|
||||
|
||||
GuiSliderBar((Rectangle){ contentX + 130, (float)rowY, 110, 30 }, NULL, NULL, &values[i], 0.0f, 1000.0f);
|
||||
}
|
||||
|
||||
118
examples/shapes/shapes_polygon_lines.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [shapes] example - polygon lines
|
||||
*
|
||||
* Example complexity rating: [★★☆☆] 2/4
|
||||
*
|
||||
* Example originally created with raylib 6.1, last time updated with raylib 6.1
|
||||
*
|
||||
* Example contributed by Matthew Roush (@MatthewRoush) and reviewed by Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||
* BSD-like license that allows static linking with closed source software
|
||||
*
|
||||
* Copyright (c) 2026 Matthew Roush (@MatthewRoush)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - polygon lines");
|
||||
|
||||
int thick = 2;
|
||||
float rotation = 0.0f;
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_UP)) thick = thick + 1;
|
||||
if (IsKeyPressed(KEY_DOWN)) thick = thick - 1;
|
||||
|
||||
thick = (thick < 1) ? 1 : (thick > 60) ? 60 : thick;
|
||||
|
||||
rotation += (360.0f/10.0f)*GetFrameTime();
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText(TextFormat("thick = %d", thick), 10, 280, 20, LIME);
|
||||
|
||||
// The square and circle outlines in the top left should match
|
||||
// The fist pair of outlines are drawn using `DrawRectangleLinesEx()` and `DrawCircleLinesEx()`
|
||||
// The second pair are drawn using `DrawPolyLinesEx()` with parameters that should visually match the first pair
|
||||
|
||||
DrawText("These should look identical!", 10, 10, 20, MAROON);
|
||||
|
||||
// Outline pair 1
|
||||
DrawRectangle(10, 40, 50, 50, LIGHTGRAY);
|
||||
DrawRectangleLinesEx((Rectangle){ 10, 40, 50, 50 }, (float)thick, RED);
|
||||
|
||||
DrawCircle(95, 65, 25, LIGHTGRAY);
|
||||
DrawCircleLinesEx((Vector2){ 95, 65 }, 25, (float)thick, RED);
|
||||
|
||||
DrawText("DrawRectangleLinesEx() and DrawCircleLinesEx()", 130, 60, 10, BLACK);
|
||||
|
||||
// Outline pair 2
|
||||
DrawPoly((Vector2){ 35, 125 }, 4, 35.355f, 45, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 35, 125 }, 4, 35.355f, 45, (float)thick, RED);
|
||||
|
||||
DrawPoly((Vector2){ 95, 125 }, 36, 25, 0, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 95, 125 }, 36, 25, 0, (float)thick, RED);
|
||||
|
||||
DrawText("DrawPolyLinesEx()", 130, 120, 10, BLACK);
|
||||
|
||||
// Some other shapes, all of these outlines should have the same looking thickness
|
||||
DrawPoly((Vector2){ 290, 220 }, 3, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 290, 220 }, 3, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
DrawPoly((Vector2){ 430, 220 }, 4, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 430, 220 }, 4, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
DrawPoly((Vector2){ 570, 220 }, 5, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 570, 220 }, 5, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
DrawPoly((Vector2){ 710, 220 }, 6, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 710, 220 }, 6, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
DrawPoly((Vector2){ 290, 360 }, 7, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 290, 360 }, 7, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
DrawPoly((Vector2){ 430, 360 }, 8, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 430, 360 }, 8, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
DrawPoly((Vector2){ 570, 360 }, 9, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 570, 360 }, 9, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
DrawPoly((Vector2){ 710, 360 }, 10, 60, rotation, LIGHTGRAY);
|
||||
DrawPolyLinesEx((Vector2){ 710, 360 }, 10, 60, rotation, (float)thick, BLUE);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||