You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(134) |
Sep
(52) |
Oct
(13) |
Nov
(342) |
Dec
(163) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(44) |
Feb
(62) |
Mar
(158) |
Apr
(38) |
May
(70) |
Jun
(58) |
Jul
(104) |
Aug
(207) |
Sep
(83) |
Oct
(122) |
Nov
(23) |
Dec
(49) |
| 2004 |
Jan
(119) |
Feb
(132) |
Mar
(192) |
Apr
(140) |
May
(77) |
Jun
(74) |
Jul
(201) |
Aug
(63) |
Sep
(102) |
Oct
(70) |
Nov
(173) |
Dec
(78) |
| 2005 |
Jan
(174) |
Feb
(197) |
Mar
(105) |
Apr
(59) |
May
(77) |
Jun
(43) |
Jul
(21) |
Aug
(18) |
Sep
(47) |
Oct
(37) |
Nov
(74) |
Dec
(50) |
| 2006 |
Jan
(44) |
Feb
(19) |
Mar
(32) |
Apr
(24) |
May
(31) |
Jun
(55) |
Jul
(138) |
Aug
(28) |
Sep
(12) |
Oct
(41) |
Nov
(58) |
Dec
(24) |
| 2007 |
Jan
(28) |
Feb
(14) |
Mar
(10) |
Apr
(68) |
May
(30) |
Jun
(26) |
Jul
(18) |
Aug
(63) |
Sep
(19) |
Oct
(29) |
Nov
(20) |
Dec
(10) |
| 2008 |
Jan
(38) |
Feb
(7) |
Mar
(37) |
Apr
(120) |
May
(41) |
Jun
(36) |
Jul
(39) |
Aug
(24) |
Sep
(28) |
Oct
(30) |
Nov
(36) |
Dec
(75) |
| 2009 |
Jan
(46) |
Feb
(22) |
Mar
(50) |
Apr
(70) |
May
(134) |
Jun
(105) |
Jul
(75) |
Aug
(34) |
Sep
(38) |
Oct
(34) |
Nov
(19) |
Dec
(20) |
| 2010 |
Jan
(11) |
Feb
(20) |
Mar
(65) |
Apr
(83) |
May
(104) |
Jun
(73) |
Jul
(78) |
Aug
(57) |
Sep
(43) |
Oct
(35) |
Nov
(9) |
Dec
(4) |
| 2011 |
Jan
(21) |
Feb
(11) |
Mar
(18) |
Apr
(10) |
May
(18) |
Jun
(15) |
Jul
(48) |
Aug
(25) |
Sep
(17) |
Oct
(45) |
Nov
(15) |
Dec
(12) |
| 2012 |
Jan
(21) |
Feb
(9) |
Mar
(12) |
Apr
(9) |
May
(9) |
Jun
(5) |
Jul
(1) |
Aug
(10) |
Sep
(12) |
Oct
(1) |
Nov
(28) |
Dec
(5) |
| 2013 |
Jan
(4) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2014 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
|
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
| 2015 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
(2) |
Nov
|
Dec
|
| 2016 |
Jan
(2) |
Feb
(1) |
Mar
(1) |
Apr
(1) |
May
(2) |
Jun
|
Jul
(1) |
Aug
(2) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
| 2017 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
1
|
2
(1) |
|
3
|
4
|
5
|
6
|
7
(1) |
8
(1) |
9
|
|
10
|
11
|
12
|
13
|
14
|
15
|
16
(3) |
|
17
|
18
|
19
|
20
|
21
|
22
|
23
|
|
24
|
25
|
26
(1) |
27
|
28
(1) |
29
|
30
(2) |
|
From: <ka...@us...> - 2011-04-30 23:56:30
|
Revision: 3521
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3521&view=rev
Author: kappa1
Date: 2011-04-30 23:56:24 +0000 (Sat, 30 Apr 2011)
Log Message:
-----------
AppletLoader: minor tweak on comments
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-04-30 23:54:24 UTC (rev 3520)
+++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-04-30 23:56:24 UTC (rev 3521)
@@ -1665,9 +1665,9 @@
}
/**
- * Check and validate jar which will be loaded into the classloader to make
- * sure that they are not corrupt. This will ensure that cached files are
- * never marked as being successfully downloaded if they are corrupt.
+ * Check and validate jars which will be loaded into the classloader to make
+ * sure that they are not corrupt. This ensures corrupt files are never marked
+ * as successfully downloadeds by the cache system.
*
* @param path - where the jars are stored
* @throws Exception if a corrupt jar is found
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ka...@us...> - 2011-04-30 23:54:31
|
Revision: 3520
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3520&view=rev
Author: kappa1
Date: 2011-04-30 23:54:24 +0000 (Sat, 30 Apr 2011)
Log Message:
-----------
AppletLoader: added jar validation to detect corruption and ensures that the cache system doesn't mark corrupt files as successfully downloads. Thx to Riven and MatthiasM for assisting with the implementation.
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-04-28 17:54:46 UTC (rev 3519)
+++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-04-30 23:54:24 UTC (rev 3520)
@@ -41,6 +41,7 @@
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.ImageObserver;
+import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -77,7 +78,11 @@
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Pack200;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedInputStream;
import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
import sun.security.util.SecurityConstants;
@@ -141,6 +146,7 @@
* <li>Matthias Mann</li>
* <li>Mickelukas</li>
* <li>NateS</li>
+ * <li>Riven</li>
* <li>Ruben01</li>
* <li>Shannon Smith</li>
* <li>pjohnsen</li>
@@ -163,21 +169,24 @@
/** extracting packages */
public static final int STATE_EXTRACTING_PACKAGES = 5;
+
+ /** validating packages */
+ public static final int STATE_VALIDATING_PACKAGES = 6;
/** updating the classpath */
- public static final int STATE_UPDATING_CLASSPATH = 6;
+ public static final int STATE_UPDATING_CLASSPATH = 7;
/** switching to real applet */
- public static final int STATE_SWITCHING_APPLET = 7;
+ public static final int STATE_SWITCHING_APPLET = 8;
/** initializing real applet */
- public static final int STATE_INITIALIZE_REAL_APPLET = 8;
+ public static final int STATE_INITIALIZE_REAL_APPLET = 9;
/** stating real applet */
- public static final int STATE_START_REAL_APPLET = 9;
+ public static final int STATE_START_REAL_APPLET = 10;
/** done */
- public static final int STATE_DONE = 10;
+ public static final int STATE_DONE = 11;
/** used to calculate length of progress bar */
protected int percentage;
@@ -261,13 +270,13 @@
protected boolean pack200Supported;
/** whether to run in headless mode */
- protected boolean headless = false;
+ protected boolean headless = false;
/** whether to switch applets in headless mode or wait longer */
- protected boolean headlessWaiting = true;
+ protected boolean headlessWaiting = true;
/** messages to be passed via liveconnect in headless mode */
- protected String[] headlessMessage;
+ protected String[] headlessMessage;
/** generic error message to display on error */
protected String[] genericErrorMessage = { "An error occured while loading the applet.",
@@ -632,6 +641,8 @@
return "Downloading packages";
case STATE_EXTRACTING_PACKAGES:
return "Extracting downloaded packages";
+ case STATE_VALIDATING_PACKAGES:
+ return "Validating packages";
case STATE_UPDATING_CLASSPATH:
return "Updating classpath";
case STATE_SWITCHING_APPLET:
@@ -827,7 +838,10 @@
extractJars(path); // 55-65%
// Extracts Native Files
- extractNatives(path); // 65-85%
+ extractNatives(path); // 65-80%
+
+ // Validate Jars // 80-90%
+ validateJars(path);
// save version information once jars downloaded successfully
if (version != null) {
@@ -1519,7 +1533,7 @@
setState(STATE_EXTRACTING_PACKAGES);
- float percentageParts = 20f/nativeJarCount; // parts for each native jar from 20%
+ float percentageParts = 15f/nativeJarCount; // parts for each native jar from 15%
// create native folder
File nativeFolder = new File(path + "natives");
@@ -1649,6 +1663,87 @@
}
}
}
+
+ /**
+ * Check and validate jar which will be loaded into the classloader to make
+ * sure that they are not corrupt. This will ensure that cached files are
+ * never marked as being successfully downloaded if they are corrupt.
+ *
+ * @param path - where the jars are stored
+ * @throws Exception if a corrupt jar is found
+ */
+ protected void validateJars(String path) throws Exception {
+
+ setState(STATE_VALIDATING_PACKAGES);
+
+ percentage = 80;
+
+ float percentageParts = 10f / urlList.length; // percentage for each file out of 10%
+
+ for (int i = 0; i < urlList.length - nativeJarCount; i++) {
+
+ debug_sleep(1000);
+
+ // if file not downloaded, no need to validate again
+ if (fileSizes[i] == -2) continue;
+
+ subtaskMessage = "Validating: " + getJarName(urlList[i]);
+
+ File file = new File(path, getJarName(urlList[i]));
+ if (!isZipValid(file)) {
+ throw new Exception("The file " + getJarName(urlList[i]) + " is corrupt!");
+ }
+
+ percentage = 80 + (int)(percentageParts * i);
+ }
+
+ subtaskMessage = "";
+ }
+
+ /**
+ * This method will check if a zip file is valid by running through it
+ * and checking for any corruption and CRC failures
+ *
+ * @param file - zip file to test
+ * @return boolean - runs false if the file is corrupt
+ */
+ protected boolean isZipValid(File file) {
+
+ try {
+ ZipFile zipFile = new ZipFile(file);
+
+ try {
+ Enumeration e = zipFile.entries();
+
+ byte[] buffer = new byte[4096];
+
+ while(e.hasMoreElements()) {
+ ZipEntry zipEntry = (ZipEntry) e.nextElement();
+
+ CRC32 crc = new CRC32();
+
+ BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(zipEntry));
+ CheckedInputStream cis = new CheckedInputStream(bis, crc);
+
+ while(cis.read(buffer, 0, buffer.length) != -1) {
+ // scroll through zip entry
+ }
+
+ if (crc.getValue() != zipEntry.getCrc()) {
+ System.out.println("CRC " + crc.getValue() + " " + zipEntry.getCrc());
+ return false; // CRC match failed, corrupt zip
+ }
+ }
+
+ return true; // valid zip file
+ } finally {
+ zipFile.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
/**
* Get Image from path provided
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ma...@us...> - 2011-04-28 17:54:52
|
Revision: 3519
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3519&view=rev
Author: matzon
Date: 2011-04-28 17:54:46 +0000 (Thu, 28 Apr 2011)
Log Message:
-----------
applying maven version patch by ruben01
Modified Paths:
--------------
trunk/LWJGL/platform_build/build-maven.xml
Modified: trunk/LWJGL/platform_build/build-maven.xml
===================================================================
--- trunk/LWJGL/platform_build/build-maven.xml 2011-04-26 11:04:12 UTC (rev 3518)
+++ trunk/LWJGL/platform_build/build-maven.xml 2011-04-28 17:54:46 UTC (rev 3519)
@@ -3,11 +3,8 @@
<property name="lwjgl.src.generated" location="${lwjgl.src}/generated" />
<property name="lwjgl.maven" location="maven" />
<property name="lwjgl.dstMaven" location="${lwjgl.temp}/maven" />
+ <property name="lwjgl.src.java" location="${lwjgl.src}/java" />
- <property name="lwjgl.src.java" location="${lwjgl.src}/java" />
-
- <property name="lwjgl-maven-version" value="2.7.0"/>
-
<fileset id="lwjgl-sources.manual.fileset" dir="${lwjgl.src.java}">
<patternset refid="lwjgl.package.pattern" />
</fileset>
@@ -23,6 +20,22 @@
<patternset refid="lwjgl_util.package.pattern" />
</fileset>
+ <target name="-fixmavenversion">
+ <script language="javascript">
+ <![CDATA[
+ importPackage(java.lang);
+ var originalVersion = project.getProperty("lwjgl.version");
+ System.out.println("LWJGL Version: " + originalVersion);
+ var mavenVersion = originalVersion;
+ if(originalVersion.match(/^[0-9]+\.[0-9]+$/)){
+ System.out.println("Fixing LWJGL Maven version (Maven version should be x.y.z)");
+ mavenVersion = originalVersion + ".0";
+ }
+ project.setNewProperty("lwjgl-maven-version",mavenVersion);
+ System.out.println("LWJGL Maven Version: " + project.getProperty("lwjgl-maven-version"));
+ ]]>
+ </script>
+ </target>
<target name="maven-full">
<antcall target="clean-java" />
@@ -34,7 +47,7 @@
<antcall target="maven"/>
</target>
- <target name="maven">
+ <target name="maven" depends="-fixmavenversion"> <!-- Added as dependency because using antcall creates a new project scope -->
<delete dir="${lwjgl.dstMaven}" quiet="true" failonerror="false" taskname="cleaning maven dist" />
<mkdir dir="${lwjgl.dstMaven}" taskname="initialiazing temp maven folder" />
<antcall target="-copylwjgljars" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ka...@us...> - 2011-04-26 11:04:20
|
Revision: 3518
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3518&view=rev
Author: kappa1
Date: 2011-04-26 11:04:12 +0000 (Tue, 26 Apr 2011)
Log Message:
-----------
AppletLoader: close fileoutputstream properly when extracting pack files. Minor clean up of extract lzma and gzip methods.
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-04-16 21:13:27 UTC (rev 3517)
+++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2011-04-26 11:04:12 UTC (rev 3518)
@@ -1385,8 +1385,7 @@
Constructor constructor = clazz.getDeclaredConstructor(InputStream.class);
InputStream inputHandle = (InputStream) constructor.newInstance(fileInputHandle);
- OutputStream outputHandle;
- outputHandle = new FileOutputStream(out);
+ OutputStream outputHandle = new FileOutputStream(out);
byte [] buffer = new byte [1<<14];
@@ -1399,9 +1398,6 @@
inputHandle.close();
outputHandle.close();
- outputHandle = null;
- inputHandle = null;
-
// delete LZMA file, as it is no longer needed
f.delete();
}
@@ -1419,8 +1415,7 @@
InputStream inputHandle = new GZIPInputStream(fileInputHandle);
- OutputStream outputHandle;
- outputHandle = new FileOutputStream(out);
+ OutputStream outputHandle = new FileOutputStream(out);
byte [] buffer = new byte [1<<14];
@@ -1433,9 +1428,6 @@
inputHandle.close();
outputHandle.close();
- outputHandle = null;
- inputHandle = null;
-
// delete GZip file, as it is no longer needed
f.delete();
}
@@ -1454,6 +1446,7 @@
Pack200.Unpacker unpacker = Pack200.newUnpacker();
unpacker.unpack(f, jostream);
jostream.close();
+ fostream.close();
// delete pack file as its no longer needed
f.delete();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ma...@us...> - 2011-04-16 21:13:34
|
Revision: 3517
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3517&view=rev
Author: matzon
Date: 2011-04-16 21:13:27 +0000 (Sat, 16 Apr 2011)
Log Message:
-----------
fixing icons as per dr_evil [http://lwjgl.org/forum/index.php/topic,3925.0.html] [proper]
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java
Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java 2011-04-16 18:38:48 UTC (rev 3516)
+++ trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java 2011-04-16 21:13:27 UTC (rev 3517)
@@ -668,16 +668,18 @@
int size = icon.limit() / 4;
if ( (((int)Math.sqrt(size)) == small_icon_size) && (!done_small) ) {
- small_icon = createIcon(small_icon_size, small_icon_size, icon.asIntBuffer());
- sendMessage(hwnd, WM_SETICON, ICON_SMALL, small_icon);
+ long small_new_icon = createIcon(small_icon_size, small_icon_size, icon.asIntBuffer());
+ sendMessage(hwnd, WM_SETICON, ICON_SMALL, small_new_icon);
freeSmallIcon();
+ small_icon = small_new_icon;
used++;
done_small = true;
}
if ( (((int)Math.sqrt(size)) == large_icon_size) && (!done_large) ) {
- large_icon = createIcon(large_icon_size, large_icon_size, icon.asIntBuffer());
- sendMessage(hwnd, WM_SETICON, ICON_BIG, large_icon);
+ long large_new_icon = createIcon(large_icon_size, large_icon_size, icon.asIntBuffer());
+ sendMessage(hwnd, WM_SETICON, ICON_BIG, large_new_icon);
freeLargeIcon();
+ large_icon = large_new_icon;
used++;
done_large = true;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ma...@us...> - 2011-04-16 18:38:54
|
Revision: 3516
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3516&view=rev
Author: matzon
Date: 2011-04-16 18:38:48 +0000 (Sat, 16 Apr 2011)
Log Message:
-----------
fixing icons as per dr_evil [http://lwjgl.org/forum/index.php/topic,3925.0.html]
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java
Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java 2011-04-16 16:41:19 UTC (rev 3515)
+++ trunk/LWJGL/src/java/org/lwjgl/opengl/WindowsDisplay.java 2011-04-16 18:38:48 UTC (rev 3516)
@@ -668,16 +668,16 @@
int size = icon.limit() / 4;
if ( (((int)Math.sqrt(size)) == small_icon_size) && (!done_small) ) {
- freeSmallIcon();
small_icon = createIcon(small_icon_size, small_icon_size, icon.asIntBuffer());
sendMessage(hwnd, WM_SETICON, ICON_SMALL, small_icon);
+ freeSmallIcon();
used++;
done_small = true;
}
if ( (((int)Math.sqrt(size)) == large_icon_size) && (!done_large) ) {
- freeLargeIcon();
large_icon = createIcon(large_icon_size, large_icon_size, icon.asIntBuffer());
sendMessage(hwnd, WM_SETICON, ICON_BIG, large_icon);
+ freeLargeIcon();
used++;
done_large = true;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ka...@us...> - 2011-04-16 16:41:25
|
Revision: 3515
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3515&view=rev
Author: kappa1
Date: 2011-04-16 16:41:19 +0000 (Sat, 16 Apr 2011)
Log Message:
-----------
ANT build : switch to using the 10.4 sdk instead of the 10.3 one for ppc builds
Modified Paths:
--------------
trunk/LWJGL/platform_build/macosx_ant/build.xml
Modified: trunk/LWJGL/platform_build/macosx_ant/build.xml
===================================================================
--- trunk/LWJGL/platform_build/macosx_ant/build.xml 2011-04-08 03:41:19 UTC (rev 3514)
+++ trunk/LWJGL/platform_build/macosx_ant/build.xml 2011-04-16 16:41:19 UTC (rev 3515)
@@ -43,7 +43,7 @@
<target name="nativelibrary" depends="init">
<property name="universal_sdkroot" location="/Developer/SDKs/MacOSX10.4u.sdk"/>
- <property name="ppc_sdkroot" location="/Developer/SDKs/MacOSX10.3.9.sdk"/>
+ <property name="ppc_sdkroot" location="/Developer/SDKs/MacOSX10.4u.sdk"/>
<property name="x86_64_sdkroot" location="/Developer/SDKs/MacOSX10.5.sdk"/>
<property name="universal_flags" value="-isysroot ${universal_sdkroot}"/>
<property name="ppc_flags" value="-isysroot ${ppc_sdkroot}"/>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sp...@us...> - 2011-04-08 03:41:25
|
Revision: 3514
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3514&view=rev
Author: spasi
Date: 2011-04-08 03:41:19 +0000 (Fri, 08 Apr 2011)
Log Message:
-----------
Fixed JDK5 compilation issue and added SpriteShootout textures.
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java
Added Paths:
-----------
trunk/LWJGL/res/ball.png
trunk/LWJGL/res/ball_sm.png
Added: trunk/LWJGL/res/ball.png
===================================================================
(Binary files differ)
Property changes on: trunk/LWJGL/res/ball.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: trunk/LWJGL/res/ball_sm.png
===================================================================
(Binary files differ)
Property changes on: trunk/LWJGL/res/ball_sm.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java 2011-04-07 21:36:19 UTC (rev 3513)
+++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java 2011-04-08 03:41:19 UTC (rev 3514)
@@ -479,7 +479,7 @@
final FloatBuffer depths = BufferUtils.createFloatBuffer(count * 2);
final float depthStep = 1.9f / count;
- float depth = Math.nextAfter(1.0f, Float.MIN_VALUE);
+ float depth = Float.parseFloat("0x1.fffffep-1");
// Front-to-back
for ( int i = 0; i < count; i++ ) {
depths.put(depth);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sp...@us...> - 2011-04-07 21:36:27
|
Revision: 3513
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3513&view=rev
Author: spasi
Date: 2011-04-07 21:36:19 +0000 (Thu, 07 Apr 2011)
Log Message:
-----------
Added support for AMD_blend_minmax_factor & NV_texture_multisample.
Added sprite rendering samples.
Fixed ContextAttribs version checking for GL41.
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java
trunk/LWJGL/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java
Added Paths:
-----------
trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/
trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java
trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java
trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutCL.java
trunk/LWJGL/src/templates/org/lwjgl/opengl/AMD_blend_minmax_factor.java
trunk/LWJGL/src/templates/org/lwjgl/opengl/NV_texture_multisample.java
Modified: trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java 2011-04-02 11:33:02 UTC (rev 3512)
+++ trunk/LWJGL/src/java/org/lwjgl/opengl/ContextAttribs.java 2011-04-07 21:36:19 UTC (rev 3513)
@@ -87,7 +87,7 @@
public ContextAttribs(final int majorVersion, final int minorVersion) {
if ( majorVersion < 0 || 4 < majorVersion ||
minorVersion < 0 ||
- (majorVersion == 4 && 0 < minorVersion) ||
+ (majorVersion == 4 && 1 < minorVersion) ||
(majorVersion == 3 && 3 < minorVersion) ||
(majorVersion == 2 && 1 < minorVersion) ||
(majorVersion == 1 && 5 < minorVersion) )
Modified: trunk/LWJGL/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java 2011-04-02 11:33:02 UTC (rev 3512)
+++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/shaders/ShadersTest.java 2011-04-07 21:36:19 UTC (rev 3513)
@@ -137,7 +137,7 @@
System.out.println("Setting display mode to: " + displayMode);
Display.setDisplayMode(displayMode);
- Display.create(new PixelFormat(8, 24, 0), "UNI".equalsIgnoreCase(args[0]) ? new ContextAttribs(3, 1) : null);
+ Display.create(new PixelFormat(8, 24, 0));
ShadersTest.displayMode = displayMode;
} catch (LWJGLException e) {
kill(e.getMessage());
Added: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java (rev 0)
+++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout.java 2011-04-07 21:36:19 UTC (rev 3513)
@@ -0,0 +1,714 @@
+package org.lwjgl.test.opengl.sprites;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.*;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.util.Random;
+import javax.imageio.ImageIO;
+
+import static org.lwjgl.opengl.EXTTransformFeedback.*;
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL12.*;
+import static org.lwjgl.opengl.GL15.*;
+import static org.lwjgl.opengl.GL20.*;
+import static org.lwjgl.opengl.GL30.*;
+
+/**
+ * Sprite rendering demo. Three implementations are supported:
+ * a) CPU animation + BufferData VBO update.
+ * b) CPU animation + MapBufferRange VBO update.
+ * c) GPU animation using transform feedback with a vertex shader.
+ *
+ * @author Spasi
+ * @since 18/3/2011
+ */
+public final class SpriteShootout {
+
+ private static final int SCREEN_WIDTH = 800;
+ private static final int SCREEN_HEIGHT = 600;
+
+ private static final int ANIMATION_TICKS = 60;
+
+ private boolean run = true;
+ private boolean render = true;
+ private boolean colorMask = true;
+ private boolean animate = true;
+ private boolean smooth;
+ private boolean vsync;
+
+ private int ballSize = 42;
+ private int ballCount = 100 * 1000;
+
+ private SpriteRenderer renderer;
+
+ // OpenGL stuff
+ private int texID;
+ private int texBigID;
+ private int texSmallID;
+
+ private SpriteShootout() {
+ }
+
+ public static void main(String[] args) {
+ try {
+ new SpriteShootout().start();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void start() throws LWJGLException {
+ try {
+ initGL();
+
+ final ContextCapabilities caps = GLContext.getCapabilities();
+ if ( caps.OpenGL30 || caps.GL_EXT_transform_feedback )
+ renderer = new SpriteRendererTF();
+ else if ( caps.GL_ARB_map_buffer_range )
+ renderer = new SpriteRendererMapped();
+ else
+ renderer = new SpriteRendererPlain();
+
+ updateBalls(ballCount);
+ run();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ destroy();
+ }
+ }
+
+ private void initGL() throws LWJGLException {
+ Display.setLocation((Display.getDisplayMode().getWidth() - SCREEN_WIDTH) / 2,
+ (Display.getDisplayMode().getHeight() - SCREEN_HEIGHT) / 2);
+ Display.setDisplayMode(new DisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT));
+ Display.setTitle("Sprite Shootout");
+ Display.create();
+ //Display.create(new PixelFormat(), new ContextAttribs(4, 1).withProfileCompatibility(true).withDebug(true));
+ //AMDDebugOutput.glDebugMessageCallbackAMD(new AMDDebugOutputCallback());
+
+ if ( !GLContext.getCapabilities().OpenGL20 )
+ throw new RuntimeException("OpenGL 2.0 is required for this demo.");
+
+ // Setup viewport
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, SCREEN_WIDTH, 0, SCREEN_HEIGHT, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+
+ // Create textures
+
+ try {
+ texSmallID = createTexture("res/ball_sm.png");
+ texBigID = createTexture("res/ball.png");
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ texID = texBigID;
+
+ // Setup rendering state
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.0f);
+
+ glColorMask(colorMask, colorMask, colorMask, false);
+ glDepthMask(false);
+ glDisable(GL_DEPTH_TEST);
+
+ // Setup geometry
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ Util.checkGLError();
+ }
+
+ private static int createTexture(final String path) throws IOException {
+ final BufferedImage img = ImageIO.read(SpriteShootout.class.getClassLoader().getResource(path));
+
+ final int w = img.getWidth();
+ final int h = img.getHeight();
+
+ final ByteBuffer buffer = readImage(img);
+
+ final int texID = glGenTextures();
+
+ glBindTexture(GL_TEXTURE_2D, texID);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
+
+ return texID;
+ }
+
+ private static ByteBuffer readImage(final BufferedImage img) throws IOException {
+ final Raster raster = img.getRaster();
+
+ final int bands = raster.getNumBands();
+
+ final int w = img.getWidth();
+ final int h = img.getHeight();
+
+ final int size = w * h * bands;
+
+ final byte[] pixels = new byte[size];
+ raster.getDataElements(0, 0, w, h, pixels);
+
+ final ByteBuffer pbuffer = BufferUtils.createByteBuffer(size);
+
+ if ( bands == 4 ) {
+ for ( int i = 0; i < (w * h * 4); i += 4 ) {
+ // Pre-multiply alpha
+ final float a = unpackUByte01(pixels[i + 3]);
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 2]) * a));
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 1]) * a));
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 0]) * a));
+ pbuffer.put(pixels[i + 3]);
+ }
+ } else if ( bands == 3 ) {
+ for ( int i = 0; i < (w * h * 3); i += 3 ) {
+ pbuffer.put(pixels[i + 2]);
+ pbuffer.put(pixels[i + 1]);
+ pbuffer.put(pixels[i + 0]);
+ }
+ } else
+ pbuffer.put(pixels, 0, size);
+
+ pbuffer.flip();
+
+ return pbuffer;
+ }
+
+ private static float unpackUByte01(final byte x) {
+ return (x & 0xFF) / 255.0f;
+ }
+
+ private static byte packUByte01(final float x) {
+ return (byte)(x * 255.0f);
+ }
+
+ private void updateBalls(final int count) {
+ System.out.println("NUMBER OF BALLS: " + count);
+ renderer.updateBalls(ballCount);
+ }
+
+ private void run() {
+ long startTime = System.currentTimeMillis() + 5000;
+ long fps = 0;
+
+ long time = Sys.getTime();
+ final int ticksPerUpdate = (int)(Sys.getTimerResolution() / ANIMATION_TICKS);
+
+ renderer.render(false, true, 0);
+
+ while ( run ) {
+ Display.processMessages();
+ handleInput();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ final long currTime = Sys.getTime();
+ final int delta = (int)(currTime - time);
+ if ( smooth || delta >= ticksPerUpdate ) {
+ renderer.render(render, animate, delta);
+ time = currTime;
+ } else
+ renderer.render(render, false, 0);
+
+ Display.update(false);
+ //Display.sync(60);
+
+ if ( startTime > System.currentTimeMillis() ) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ System.out.println("FPS: " + (Math.round(fps / (timeUsed / 1000.0) * 10) / 10.0) + ", Balls: " + ballCount);
+ fps = 0;
+ }
+ }
+ }
+
+ private void handleInput() {
+ if ( Display.isCloseRequested() )
+ run = false;
+
+ while ( Keyboard.next() ) {
+ if ( Keyboard.getEventKeyState() )
+ continue;
+
+ switch ( Keyboard.getEventKey() ) {
+ case Keyboard.KEY_1:
+ case Keyboard.KEY_2:
+ case Keyboard.KEY_3:
+ case Keyboard.KEY_4:
+ case Keyboard.KEY_5:
+ case Keyboard.KEY_6:
+ case Keyboard.KEY_7:
+ case Keyboard.KEY_8:
+ case Keyboard.KEY_9:
+ case Keyboard.KEY_0:
+ ballCount = 1 << (Keyboard.getEventKey() - Keyboard.KEY_1);
+ updateBalls(ballCount);
+ break;
+ case Keyboard.KEY_ADD:
+ case Keyboard.KEY_SUBTRACT:
+ int mult;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT) )
+ mult = 1000;
+ else if ( Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU) )
+ mult = 100;
+ else if ( Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) )
+ mult = 10;
+ else
+ mult = 1;
+ if ( Keyboard.getEventKey() == Keyboard.KEY_SUBTRACT )
+ mult = -mult;
+ ballCount += mult * 100;
+ if ( ballCount <= 0 )
+ ballCount = 1;
+ updateBalls(ballCount);
+ break;
+ case Keyboard.KEY_ESCAPE:
+ run = false;
+ break;
+ case Keyboard.KEY_A:
+ animate = !animate;
+ System.out.println("Animation is now " + (animate ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_C:
+ colorMask = !colorMask;
+ glColorMask(colorMask, colorMask, colorMask, false);
+ System.out.println("Color mask is now " + (colorMask ? "on" : "off") + ".");
+ // Disable alpha test when color mask is off, else we get no benefit.
+ if ( colorMask ) {
+ glEnable(GL_BLEND);
+ glEnable(GL_ALPHA_TEST);
+ } else {
+ glDisable(GL_BLEND);
+ glDisable(GL_ALPHA_TEST);
+ }
+ break;
+ case Keyboard.KEY_R:
+ render = !render;
+ System.out.println("Rendering is now " + (render ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_S:
+ smooth = !smooth;
+ System.out.println("Smooth animation is now " + (smooth ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_T:
+ if ( texID == texBigID ) {
+ texID = texSmallID;
+ ballSize = 16;
+ } else {
+ texID = texBigID;
+ ballSize = 42;
+ }
+ renderer.updateBallSize();
+ glBindTexture(GL_TEXTURE_2D, texID);
+ System.out.println("Now using the " + (texID == texBigID ? "big" : "small") + " texture.");
+ break;
+ case Keyboard.KEY_V:
+ vsync = !vsync;
+ Display.setVSyncEnabled(vsync);
+ System.out.println("VSYNC is now " + (vsync ? "enabled" : "disabled") + ".");
+ break;
+ }
+ }
+
+ while ( Mouse.next() ) ;
+ }
+
+ private void destroy() {
+ Display.destroy();
+ }
+
+ private abstract class SpriteRenderer {
+
+ protected float[] transform = { };
+
+ protected int vshID;
+ protected int progID;
+
+ protected void createProgram() {
+ final int fshID = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fshID, "uniform sampler2D COLOR_MAP;\n" +
+ "void main(void) {\n" +
+ " gl_FragColor = texture2D(COLOR_MAP, gl_PointCoord);\n" +
+ "}");
+ glCompileShader(fshID);
+ if ( glGetShader(fshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(fshID, glGetShader(fshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile fragment shader.");
+ }
+
+ progID = glCreateProgram();
+ glAttachShader(progID, vshID);
+ glAttachShader(progID, fshID);
+ glLinkProgram(progID);
+ if ( glGetProgram(progID, GL_LINK_STATUS) == GL_FALSE ) {
+ System.out.println(glGetProgramInfoLog(progID, glGetProgram(progID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to link shader program.");
+ }
+
+ glUseProgram(progID);
+ glUniform1i(glGetUniformLocation(progID, "COLOR_MAP"), 0);
+
+ updateBallSize();
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ }
+
+ public void updateBallSize() {
+ glPointSize(ballSize);
+ }
+
+ public void updateBalls(final int count) {
+ final Random random = new Random();
+
+ final float[] newTransform = new float[count * 4];
+ System.arraycopy(transform, 0, newTransform, 0, Math.min(transform.length, newTransform.length));
+ if ( newTransform.length > transform.length ) {
+ for ( int i = transform.length; i < newTransform.length; ) {
+ newTransform[i++] = (int)(random.nextFloat() * (SCREEN_WIDTH - ballSize) + ballSize * 0.5f);
+ newTransform[i++] = (int)(random.nextFloat() * (SCREEN_HEIGHT - ballSize) + ballSize * 0.5f);
+ newTransform[i++] = random.nextFloat() * 0.4f - 0.2f;
+ newTransform[i++] = random.nextFloat() * 0.4f - 0.2f;
+ }
+ }
+ transform = newTransform;
+ }
+
+ protected void animate(final FloatBuffer geom, final int ballIndex, final int batchSize, final int delta) {
+ final float[] transform = this.transform;
+
+ final float ballRadius = ballSize * 0.5f;
+ final float boundW = SCREEN_WIDTH - ballRadius;
+ final float boundH = SCREEN_HEIGHT - ballRadius;
+
+ for ( int b = ballIndex * 4, len = (ballIndex + batchSize) * 4; b < len; b += 4 ) {
+ float x = transform[b + 0];
+ float dx = transform[b + 2];
+
+ x += dx * delta;
+ if ( x < ballRadius ) {
+ x = ballRadius;
+ transform[b + 2] = -dx;
+ } else if ( x > boundW ) {
+ x = boundW;
+ transform[b + 2] = -dx;
+ }
+ transform[b + 0] = x;
+
+ float y = transform[b + 1];
+ float dy = transform[b + 3];
+
+ y += dy * delta;
+ if ( y < ballRadius ) {
+ y = ballRadius;
+ transform[b + 3] = -dy;
+ } else if ( y > boundH ) {
+ y = boundH;
+ transform[b + 3] = -dy;
+ }
+ transform[b + 1] = y;
+
+ geom.put(x).put(y);
+ }
+ geom.clear();
+ }
+
+ protected abstract void render(boolean render, boolean animate, int delta);
+
+ }
+
+ private abstract class SpriteRendererBatched extends SpriteRenderer {
+
+ protected static final int BALLS_PER_BATCH = 10 * 1000;
+
+ SpriteRendererBatched() {
+ vshID = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vshID, "void main(void) {\n" +
+ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" +
+ "}");
+ glCompileShader(vshID);
+ if ( glGetShader(vshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(vshID, glGetShader(vshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile vertex shader.");
+ }
+
+ createProgram();
+ }
+
+ }
+
+ private class SpriteRendererPlain extends SpriteRendererBatched {
+
+ private final FloatBuffer geom;
+
+ protected int[] animVBO;
+
+ SpriteRendererPlain() {
+ System.out.println("Shootout Implementation: CPU animation & BufferData");
+ geom = BufferUtils.createFloatBuffer(BALLS_PER_BATCH * 4 * 2);
+ }
+
+ public void updateBalls(final int count) {
+ super.updateBalls(count);
+
+ final int batchCount = count / BALLS_PER_BATCH + (count % BALLS_PER_BATCH == 0 ? 0 : 1);
+ if ( animVBO != null && batchCount == animVBO.length )
+ return;
+
+ final int[] newAnimVBO = new int[batchCount];
+ if ( animVBO != null ) {
+ System.arraycopy(animVBO, 0, newAnimVBO, 0, Math.min(animVBO.length, newAnimVBO.length));
+ for ( int i = newAnimVBO.length; i < animVBO.length; i++ )
+ glDeleteBuffers(animVBO[i]);
+ }
+ for ( int i = animVBO == null ? 0 : animVBO.length; i < newAnimVBO.length; i++ ) {
+ newAnimVBO[i] = glGenBuffers();
+ glBindBuffer(GL_ARRAY_BUFFER, newAnimVBO[i]);
+ }
+
+ animVBO = newAnimVBO;
+ }
+
+ public void render(final boolean render, final boolean animate, final int delta) {
+ int batchSize = Math.min(ballCount, BALLS_PER_BATCH);
+ int ballIndex = 0;
+ int vboIndex = 0;
+ while ( ballIndex < ballCount ) {
+ glBindBuffer(GL_ARRAY_BUFFER, animVBO[vboIndex++]);
+
+ if ( animate )
+ animate(ballIndex, batchSize, delta);
+
+ if ( render ) {
+ glVertexPointer(2, GL_FLOAT, 0, 0);
+ glDrawArrays(GL_POINTS, 0, batchSize);
+ }
+
+ ballIndex += batchSize;
+ batchSize = Math.min(ballCount - ballIndex, BALLS_PER_BATCH);
+ }
+ }
+
+ private void animate(final int ballIndex, final int batchSize, final int delta) {
+ animate(geom, ballIndex, batchSize, delta);
+
+ glBufferData(GL_ARRAY_BUFFER, geom.capacity() * 4, GL_STREAM_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, geom);
+ }
+ }
+
+ private class SpriteRendererMapped extends SpriteRendererBatched {
+
+ private ByteBuffer[] mapBuffer;
+ private FloatBuffer[] geomBuffer;
+
+ protected int animVBO;
+
+ SpriteRendererMapped() {
+ System.out.println("Shootout Implementation: CPU animation & MapBufferRange");
+ }
+
+ public void updateBalls(final int count) {
+ super.updateBalls(count);
+
+ final int batchCount = count / BALLS_PER_BATCH + (count % BALLS_PER_BATCH == 0 ? 0 : 1);
+ mapBuffer = new ByteBuffer[batchCount];
+ geomBuffer = new FloatBuffer[batchCount];
+
+ animVBO = glGenBuffers();
+ glBindBuffer(GL_ARRAY_BUFFER, animVBO);
+ glBufferData(GL_ARRAY_BUFFER, ballCount * (2 * 4), GL_DYNAMIC_DRAW);
+ glVertexPointer(2, GL_FLOAT, 0, 0);
+ }
+
+ public void render(final boolean render, final boolean animate, final int delta) {
+ int batchSize = Math.min(ballCount, BALLS_PER_BATCH);
+ int ballIndex = 0;
+ int batchIndex = 0;
+ while ( ballIndex < ballCount ) {
+ if ( animate ) {
+ final ByteBuffer buffer = glMapBufferRange(GL_ARRAY_BUFFER,
+ ballIndex * (2 * 4),
+ batchSize * (2 * 4),
+ GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT,
+ mapBuffer[batchIndex]);
+ if ( buffer != mapBuffer[batchIndex] ) {
+ mapBuffer[batchIndex] = buffer;
+ geomBuffer[batchIndex] = mapBuffer[batchIndex].asFloatBuffer();
+ }
+
+ animate(geomBuffer[batchIndex], ballIndex, batchSize, delta);
+
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+ }
+
+ if ( render )
+ glDrawArrays(GL_POINTS, ballIndex, batchSize);
+
+ batchIndex++;
+ ballIndex += batchSize;
+ batchSize = Math.min(ballCount - ballIndex, BALLS_PER_BATCH);
+ }
+ }
+ }
+
+ private class SpriteRendererTF extends SpriteRenderer {
+
+ private int progIDTF;
+ private int ballSizeLoc;
+ private int deltaLoc;
+
+ private int[] tfVBO = new int[2];
+ private int currVBO;
+
+ SpriteRendererTF() {
+ System.out.println("Shootout Implementation: TF GPU animation");
+
+ // Transform-feedback program
+
+ final int vshID = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vshID, "#version 130\n" +
+ "const float WIDTH = " + SCREEN_WIDTH + ";\n" +
+ "const float HEIGHT = " + SCREEN_HEIGHT + ";\n" +
+ "uniform float ballSize;\n" + // ballSize / 2
+ "uniform float delta;\n" +
+ "void main(void) {\n" +
+ " vec4 anim = gl_Vertex;\n" +
+ " anim.xy = anim.xy + anim.zw * delta;\n" +
+ " vec2 animC = clamp(anim.xy, vec2(ballSize), vec2(WIDTH - ballSize, HEIGHT - ballSize));\n" +
+ " if ( anim.x != animC.x ) anim.z = -anim.z;\n" +
+ " if ( anim.y != animC.y ) anim.w = -anim.w;\n" +
+ " gl_Position = vec4(animC, anim.zw);\n" +
+ "}");
+ glCompileShader(vshID);
+ if ( glGetShader(vshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(vshID, glGetShader(vshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile vertex shader.");
+ }
+
+ progIDTF = glCreateProgram();
+ glAttachShader(progIDTF, vshID);
+ glTransformFeedbackVaryings(progIDTF, new CharSequence[] { "gl_Position" }, GL_SEPARATE_ATTRIBS);
+ glLinkProgram(progIDTF);
+ if ( glGetProgram(progIDTF, GL_LINK_STATUS) == GL_FALSE ) {
+ System.out.println(glGetProgramInfoLog(progIDTF, glGetProgram(progIDTF, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to link shader program.");
+ }
+
+ glUseProgram(progIDTF);
+
+ ballSizeLoc = glGetUniformLocation(progIDTF, "ballSize");
+ deltaLoc = glGetUniformLocation(progIDTF, "delta");
+
+ glUniform1f(ballSizeLoc, ballSize * 0.5f);
+
+ // -----------------
+
+ this.vshID = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(this.vshID, "void main(void) {\n" +
+ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" +
+ "}");
+ glCompileShader(this.vshID);
+ if ( glGetShader(this.vshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(this.vshID, glGetShader(this.vshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile vertex shader.");
+ }
+
+ createProgram();
+ }
+
+ public void updateBallSize() {
+ glUseProgram(progIDTF);
+ glUniform1f(ballSizeLoc, ballSize * 0.5f);
+
+ glUseProgram(progID);
+ super.updateBallSize();
+ }
+
+ public void updateBalls(final int count) {
+ super.updateBalls(count);
+
+ if ( tfVBO[0] != 0 ) {
+ for ( int i = 0; i < tfVBO.length; i++ )
+ glDeleteBuffers(tfVBO[i]);
+ }
+
+ final FloatBuffer transform = BufferUtils.createFloatBuffer(count * 4);
+ transform.put(this.transform);
+ transform.flip();
+
+ for ( int i = 0; i < tfVBO.length; i++ ) {
+ tfVBO[i] = glGenBuffers();
+ glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tfVBO[i]);
+ glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, transform, GL_STATIC_DRAW);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, tfVBO[0]);
+ glVertexPointer(2, GL_FLOAT, (4 * 4), 0);
+ }
+
+ public void render(final boolean render, final boolean animate, final int delta) {
+ if ( animate ) {
+ glUseProgram(progIDTF);
+ glUniform1f(deltaLoc, delta);
+
+ final int vbo = currVBO;
+ currVBO = 1 - currVBO;
+
+ glBindBuffer(GL_ARRAY_BUFFER, tfVBO[vbo]);
+ glVertexPointer(4, GL_FLOAT, 0, 0);
+
+ glEnable(GL_RASTERIZER_DISCARD);
+ if ( GLContext.getCapabilities().OpenGL30 ) {
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfVBO[1 - vbo]);
+
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, ballCount);
+ glEndTransformFeedback();
+ } else {
+ glBindBufferBaseEXT(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0, tfVBO[1 - vbo]);
+
+ glBeginTransformFeedbackEXT(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, ballCount);
+ glEndTransformFeedbackEXT();
+ }
+ glDisable(GL_RASTERIZER_DISCARD);
+
+ glUseProgram(progID);
+ glVertexPointer(2, GL_FLOAT, (4 * 4), 0);
+ }
+
+ if ( render )
+ glDrawArrays(GL_POINTS, 0, ballCount);
+ }
+
+ }
+
+}
\ No newline at end of file
Added: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java (rev 0)
+++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootout2P.java 2011-04-07 21:36:19 UTC (rev 3513)
@@ -0,0 +1,591 @@
+package org.lwjgl.test.opengl.sprites;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.*;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.util.Random;
+import javax.imageio.ImageIO;
+
+import static org.lwjgl.opengl.EXTTransformFeedback.*;
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL15.*;
+import static org.lwjgl.opengl.GL20.*;
+import static org.lwjgl.opengl.GL30.*;
+import static org.lwjgl.opengl.GL32.*;
+
+/**
+ * Sprite rendering demo. In this version we're doing the animation
+ * computations on the GPU, using transform feedback and a vertex
+ * shader, then rendering is performed in 2 passes, with depth testing
+ * enabled:
+ * 1) Sprites are rendered front-to-back, opaque fragments only, blending is disabled.
+ * 2) Sprites are rendered back-to-front, transparent fragments only, blending is enabled.
+ * Sorting is free, because we're animating double the amount of sprites rendered, the
+ * first batch is sorted f2b, the second is sorted b2f. Ordering is achieved by modifying
+ * the z-axis position of the sprites in the vertex shader.
+ *
+ * @author Spasi
+ * @since 18/3/2011
+ */
+public final class SpriteShootout2P {
+
+ private static final int SCREEN_WIDTH = 800;
+ private static final int SCREEN_HEIGHT = 600;
+
+ private static final int ANIMATION_TICKS = 60;
+
+ private boolean run = true;
+ private boolean render = true;
+ private boolean colorMask = true;
+ private boolean animate = true;
+ private boolean smooth;
+ private boolean vsync;
+
+ private int ballSize = 42;
+ private int ballCount = 100 * 1000;
+
+ private SpriteRenderer renderer;
+
+ // OpenGL stuff
+ private int texID;
+ private int texBigID;
+ private int texSmallID;
+
+ private SpriteShootout2P() {
+ }
+
+ public static void main(String[] args) {
+ try {
+ new SpriteShootout2P().start();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void start() throws LWJGLException {
+ try {
+ initGL();
+
+ renderer = new SpriteRendererTF();
+
+ updateBalls(ballCount);
+ run();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ destroy();
+ }
+ }
+
+ private void initGL() throws LWJGLException {
+ Display.setLocation((Display.getDisplayMode().getWidth() - SCREEN_WIDTH) / 2,
+ (Display.getDisplayMode().getHeight() - SCREEN_HEIGHT) / 2);
+ Display.setDisplayMode(new DisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT));
+ Display.setTitle("Sprite Shootout 2-pass");
+ Display.create(new PixelFormat(0, 24, 0));
+ //Display.create(new PixelFormat(), new ContextAttribs(4, 1).withProfileCompatibility(true).withDebug(true));
+ //AMDDebugOutput.glDebugMessageCallbackAMD(new AMDDebugOutputCallback());
+
+ final ContextCapabilities caps = GLContext.getCapabilities();
+ if ( !(caps.OpenGL30 || (caps.OpenGL20 && caps.GL_EXT_transform_feedback)) )
+ throw new RuntimeException("OpenGL 3.0 or 2.0 + EXT_transform_feedback is required for this demo.");
+
+ // Setup viewport
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, SCREEN_WIDTH, 0, SCREEN_HEIGHT, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+
+ // Create textures
+
+ try {
+ texSmallID = createTexture("res/ball_sm.png");
+ texBigID = createTexture("res/ball.png");
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ texID = texBigID;
+
+ // Setup rendering state
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_ALPHA_TEST);
+
+ glColorMask(colorMask, colorMask, colorMask, false);
+ glDepthMask(true);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glClearDepth(1.0f);
+
+ // Setup geometry
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ Util.checkGLError();
+ }
+
+ private static int createTexture(final String path) throws IOException {
+ final BufferedImage img = ImageIO.read(SpriteShootout2P.class.getClassLoader().getResource(path));
+
+ final int w = img.getWidth();
+ final int h = img.getHeight();
+
+ final ByteBuffer buffer = readImage(img);
+
+ final int texID = glGenTextures();
+
+ glBindTexture(GL_TEXTURE_2D, texID);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
+
+ return texID;
+ }
+
+ private static ByteBuffer readImage(final BufferedImage img) throws IOException {
+ final Raster raster = img.getRaster();
+
+ final int bands = raster.getNumBands();
+
+ final int w = img.getWidth();
+ final int h = img.getHeight();
+
+ final int size = w * h * bands;
+
+ final byte[] pixels = new byte[size];
+ raster.getDataElements(0, 0, w, h, pixels);
+
+ final ByteBuffer pbuffer = BufferUtils.createByteBuffer(size);
+
+ if ( bands == 4 ) {
+ for ( int i = 0; i < (w * h * 4); i += 4 ) {
+ // Pre-multiply alpha
+ final float a = unpackUByte01(pixels[i + 3]);
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 2]) * a));
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 1]) * a));
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 0]) * a));
+ pbuffer.put(pixels[i + 3]);
+ }
+ } else if ( bands == 3 ) {
+ for ( int i = 0; i < (w * h * 3); i += 3 ) {
+ pbuffer.put(pixels[i + 2]);
+ pbuffer.put(pixels[i + 1]);
+ pbuffer.put(pixels[i + 0]);
+ }
+ } else
+ pbuffer.put(pixels, 0, size);
+
+ pbuffer.flip();
+
+ return pbuffer;
+ }
+
+ private static float unpackUByte01(final byte x) {
+ return (x & 0xFF) / 255.0f;
+ }
+
+ private static byte packUByte01(final float x) {
+ return (byte)(x * 255.0f);
+ }
+
+ private void updateBalls(final int count) {
+ System.out.println("NUMBER OF BALLS: " + count);
+ renderer.updateBalls(ballCount);
+ }
+
+ private void run() {
+ long startTime = System.currentTimeMillis() + 5000;
+ long fps = 0;
+
+ long time = Sys.getTime();
+ final int ticksPerUpdate = (int)(Sys.getTimerResolution() / ANIMATION_TICKS);
+
+ renderer.render(false, true, 0);
+
+ while ( run ) {
+ Display.processMessages();
+ handleInput();
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ final long currTime = Sys.getTime();
+ final int delta = (int)(currTime - time);
+ if ( smooth || delta >= ticksPerUpdate ) {
+ renderer.render(render, animate, delta);
+ time = currTime;
+ } else
+ renderer.render(render, false, 0);
+
+ Display.update(false);
+ //Display.sync(60);
+
+ if ( startTime > System.currentTimeMillis() ) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ System.out.println("FPS: " + (Math.round(fps / (timeUsed / 1000.0) * 10) / 10.0) + ", Balls: " + ballCount);
+ fps = 0;
+ }
+ }
+ }
+
+ private void handleInput() {
+ if ( Display.isCloseRequested() )
+ run = false;
+
+ while ( Keyboard.next() ) {
+ if ( Keyboard.getEventKeyState() )
+ continue;
+
+ switch ( Keyboard.getEventKey() ) {
+ case Keyboard.KEY_1:
+ case Keyboard.KEY_2:
+ case Keyboard.KEY_3:
+ case Keyboard.KEY_4:
+ case Keyboard.KEY_5:
+ case Keyboard.KEY_6:
+ case Keyboard.KEY_7:
+ case Keyboard.KEY_8:
+ case Keyboard.KEY_9:
+ case Keyboard.KEY_0:
+ ballCount = 1 << (Keyboard.getEventKey() - Keyboard.KEY_1);
+ updateBalls(ballCount);
+ break;
+ case Keyboard.KEY_ADD:
+ case Keyboard.KEY_SUBTRACT:
+ int mult;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT) ) {
+ mult = 1000;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) )
+ mult *= 5;
+ } else if ( Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU) )
+ mult = 100;
+ else if ( Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) )
+ mult = 10;
+ else
+ mult = 1;
+ if ( Keyboard.getEventKey() == Keyboard.KEY_SUBTRACT )
+ mult = -mult;
+ ballCount += mult * 100;
+ if ( ballCount <= 0 )
+ ballCount = 1;
+ updateBalls(ballCount);
+ break;
+ case Keyboard.KEY_ESCAPE:
+ run = false;
+ break;
+ case Keyboard.KEY_A:
+ animate = !animate;
+ System.out.println("Animation is now " + (animate ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_C:
+ colorMask = !colorMask;
+ glColorMask(colorMask, colorMask, colorMask, false);
+ System.out.println("Color mask is now " + (colorMask ? "on" : "off") + ".");
+ // Disable alpha test when color mask is off, else we get no benefit.
+ if ( colorMask ) {
+ glEnable(GL_BLEND);
+ glEnable(GL_ALPHA_TEST);
+ } else {
+ glDisable(GL_BLEND);
+ glDisable(GL_ALPHA_TEST);
+ }
+ break;
+ case Keyboard.KEY_R:
+ render = !render;
+ System.out.println("Rendering is now " + (render ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_S:
+ smooth = !smooth;
+ System.out.println("Smooth animation is now " + (smooth ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_T:
+ if ( texID == texBigID ) {
+ texID = texSmallID;
+ ballSize = 16;
+ } else {
+ texID = texBigID;
+ ballSize = 42;
+ }
+ renderer.updateBallSize();
+ glBindTexture(GL_TEXTURE_2D, texID);
+ System.out.println("Now using the " + (texID == texBigID ? "big" : "small") + " texture.");
+ break;
+ case Keyboard.KEY_V:
+ vsync = !vsync;
+ Display.setVSyncEnabled(vsync);
+ System.out.println("VSYNC is now " + (vsync ? "enabled" : "disabled") + ".");
+ break;
+ }
+ }
+
+ while ( Mouse.next() ) ;
+ }
+
+ private void destroy() {
+ Display.destroy();
+ }
+
+ private abstract class SpriteRenderer {
+
+ protected int progID;
+
+ protected void createPrograms(final int vshID) {
+ // Opaque pass
+
+ final int fshID = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fshID, "uniform sampler2D COLOR_MAP;\n" +
+ "void main(void) {\n" +
+ " gl_FragColor = texture2D(COLOR_MAP, gl_PointCoord);\n" +
+ "}");
+ glCompileShader(fshID);
+ if ( glGetShader(fshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(fshID, glGetShader(fshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile fragment shader.");
+ }
+
+ progID = glCreateProgram();
+ glAttachShader(progID, vshID);
+ glAttachShader(progID, fshID);
+ glLinkProgram(progID);
+ if ( glGetProgram(progID, GL_LINK_STATUS) == GL_FALSE ) {
+ System.out.println(glGetProgramInfoLog(progID, glGetProgram(progID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to link shader program.");
+ }
+
+ glUseProgram(progID);
+ glUniform1i(glGetUniformLocation(progID, "COLOR_MAP"), 0);
+
+ updateBallSize();
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ }
+
+ public void updateBallSize() {
+ glPointSize(ballSize);
+ }
+
+ protected abstract void updateBalls(final int count);
+
+ protected abstract void render(boolean render, boolean animate, int delta);
+
+ }
+
+ private class SpriteRendererTF extends SpriteRenderer {
+
+ private int progIDTF;
+ private int ballSizeLoc;
+ private int deltaLoc;
+
+ private int[] tfVBO = new int[2];
+ private int currVBO;
+
+ private int depthVBO;
+ private int depthLoc;
+
+ SpriteRendererTF() {
+ System.out.println("Shootout Implementation: TF GPU animation & 2-pass rendering");
+
+ // Transform-feedback program
+
+ int vshID = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vshID, "#version 130\n" +
+ "const float WIDTH = " + SCREEN_WIDTH + ";\n" +
+ "const float HEIGHT = " + SCREEN_HEIGHT + ";\n" +
+ "uniform float ballSize;\n" + // ballSize / 2
+ "uniform float delta;\n" +
+ "void main(void) {\n" +
+ " vec4 anim = gl_Vertex;\n" +
+ " anim.xy = anim.xy + anim.zw * delta;\n" +
+ " vec2 animC = clamp(anim.xy, vec2(ballSize), vec2(WIDTH - ballSize, HEIGHT - ballSize));\n" +
+ " if ( anim.x != animC.x ) anim.z = -anim.z;\n" +
+ " if ( anim.y != animC.y ) anim.w = -anim.w;\n" +
+ " gl_Position = vec4(animC, anim.zw);\n" +
+ "}");
+ glCompileShader(vshID);
+ if ( glGetShader(vshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(vshID, glGetShader(vshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile vertex shader.");
+ }
+
+ progIDTF = glCreateProgram();
+ glAttachShader(progIDTF, vshID);
+ glTransformFeedbackVaryings(progIDTF, new CharSequence[] { "gl_Position" }, GL_SEPARATE_ATTRIBS);
+ glLinkProgram(progIDTF);
+ if ( glGetProgram(progIDTF, GL_LINK_STATUS) == GL_FALSE ) {
+ System.out.println(glGetProgramInfoLog(progIDTF, glGetProgram(progIDTF, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to link shader program.");
+ }
+
+ glUseProgram(progIDTF);
+
+ ballSizeLoc = glGetUniformLocation(progIDTF, "ballSize");
+ deltaLoc = glGetUniformLocation(progIDTF, "delta");
+
+ glUniform1f(ballSizeLoc, ballSize * 0.5f);
+
+ // -----------------
+
+ vshID = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vshID, "#version 130\n" +
+ "in float depth;\n" +
+ "void main(void) {\n" +
+ " gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xy, depth, gl_Vertex.w);\n" +
+ "}");
+ glCompileShader(vshID);
+ if ( glGetShader(vshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(vshID, glGetShader(vshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile vertex shader.");
+ }
+
+ createPrograms(vshID);
+
+ depthLoc = glGetAttribLocation(progID, "depth");
+
+ // -----------------
+ }
+
+ public void updateBallSize() {
+ glUseProgram(progIDTF);
+ glUniform1f(ballSizeLoc, ballSize * 0.5f);
+
+ super.updateBallSize();
+ }
+
+ public void updateBalls(final int count) {
+ // Depth data
+
+ final FloatBuffer depths = BufferUtils.createFloatBuffer(count * 2);
+ final float depthStep = 1.9f / count;
+ float depth = Math.nextAfter(1.0f, Float.MIN_VALUE);
+ // Front-to-back
+ for ( int i = 0; i < count; i++ ) {
+ depths.put(depth);
+ depth -= depthStep;
+ }
+ // Back-to-front
+ for ( int i = 0; i < count; i++ )
+ depths.put(depths.get(count - 1 - i));
+ depths.flip();
+
+ if ( depthVBO != 0 )
+ glDeleteBuffers(depthVBO);
+
+ depthVBO = glGenBuffers();
+ glBindBuffer(GL_ARRAY_BUFFER, depthVBO);
+ glBufferData(GL_ARRAY_BUFFER, depths, GL_STATIC_DRAW);
+
+ glEnableVertexAttribArray(depthLoc);
+ glVertexAttribPointer(depthLoc, 1, GL_FLOAT, false, 0, 0);
+
+ // Animation data
+
+ final FloatBuffer transform = BufferUtils.createFloatBuffer(count * 2 * 4);
+ // Front-to-back
+ final Random random = new Random();
+ for ( int i = 0; i < count; i++ ) {
+ transform.put((int)(random.nextFloat() * (SCREEN_WIDTH - ballSize) + ballSize * 0.5f));
+ transform.put((int)(random.nextFloat() * (SCREEN_HEIGHT - ballSize) + ballSize * 0.5f));
+ transform.put(random.nextFloat() * 0.4f - 0.2f);
+ transform.put(random.nextFloat() * 0.4f - 0.2f);
+ }
+ // Back-to-front
+ for ( int i = 0; i < count; i++ ) {
+ final int offset = (count - 1 - i) * 4;
+ transform.put(transform.get(offset + 0));
+ transform.put(transform.get(offset + 1));
+ transform.put(transform.get(offset + 2));
+ transform.put(transform.get(offset + 3));
+ }
+ transform.flip();
+
+ if ( tfVBO[0] != 0 ) {
+ for ( int i = 0; i < tfVBO.length; i++ )
+ glDeleteBuffers(tfVBO[i]);
+ }
+
+ for ( int i = 0; i < tfVBO.length; i++ ) {
+ tfVBO[i] = glGenBuffers();
+ glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tfVBO[i]);
+ glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, transform, GL_STATIC_DRAW);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, tfVBO[0]);
+ glVertexPointer(2, GL_FLOAT, (4 * 4), 0);
+ }
+
+ public void render(final boolean render, final boolean animate, final int delta) {
+ if ( animate ) {
+ glDisableVertexAttribArray(depthLoc);
+
+ final int vbo = currVBO;
+ currVBO = 1 - currVBO;
+
+ glUseProgram(progIDTF);
+ glUniform1f(deltaLoc, delta);
+
+ glBindBuffer(GL_ARRAY_BUFFER, tfVBO[vbo]);
+ glVertexPointer(4, GL_FLOAT, 0, 0);
+
+ glEnable(GL_RASTERIZER_DISCARD);
+ if ( GLContext.getCapabilities().OpenGL30 ) {
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfVBO[1 - vbo]);
+
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, ballCount * 2);
+ glEndTransformFeedback();
+ } else {
+ glBindBufferBaseEXT(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0, tfVBO[1 - vbo]);
+
+ glBeginTransformFeedbackEXT(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, ballCount * 2);
+ glEndTransformFeedbackEXT();
+ }
+ glDisable(GL_RASTERIZER_DISCARD);
+
+ glUseProgram(progID);
+ glVertexPointer(2, GL_FLOAT, (4 * 4), 0);
+
+ glEnableVertexAttribArray(depthLoc);
+ }
+
+ if ( render ) {
+ // Render front-to-back opaque pass
+ glAlphaFunc(GL_EQUAL, 1.0f);
+ glDisable(GL_BLEND);
+ glDrawArrays(GL_POINTS, 0, ballCount);
+ glEnable(GL_BLEND);
+
+ // Render back-to-front transparent pass
+ glAlphaFunc(GL_GREATER, 0.0f); // Fragments with alpha == 1.0 are early-depth-rejected.
+ glDepthMask(false);
+ glDrawArrays(GL_POINTS, ballCount, ballCount);
+ glDepthMask(true);
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
Added: trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutCL.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutCL.java (rev 0)
+++ trunk/LWJGL/src/java/org/lwjgl/test/opengl/sprites/SpriteShootoutCL.java 2011-04-07 21:36:19 UTC (rev 3513)
@@ -0,0 +1,559 @@
+package org.lwjgl.test.opengl.sprites;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.LWJGLException;
+import org.lwjgl.PointerBuffer;
+import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opencl.*;
+import org.lwjgl.opencl.api.Filter;
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GLContext;
+import org.lwjgl.opengl.Util;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.List;
+import java.util.Random;
+import javax.imageio.ImageIO;
+
+import static org.lwjgl.opencl.CL10.*;
+import static org.lwjgl.opencl.CL10GL.*;
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL12.*;
+import static org.lwjgl.opengl.GL15.*;
+import static org.lwjgl.opengl.GL20.*;
+
+/**
+ * Sprite rendering demo. In this version OpenCL is used for the animation
+ * computations. CL_KHR_gl_sharing is required for sharing the animation
+ * data with OpenGL for rendering.
+ *
+ * @author Spasi
+ * @since 18/3/2011
+ */
+public final class SpriteShootoutCL {
+
+ private static final int SCREEN_WIDTH = 800;
+ private static final int SCREEN_HEIGHT = 600;
+
+ private static final int ANIMATION_TICKS = 60;
+
+ private boolean run = true;
+ private boolean render = true;
+ private boolean colorMask = true;
+ private boolean animate = true;
+ private boolean smooth;
+ private boolean vsync;
+
+ private int ballSize = 42;
+ private int ballCount = 100 * 1000;
+
+ private SpriteRenderer renderer;
+
+ // OpenGL stuff
+ private int texID;
+ private int texBigID;
+ private int texSmallID;
+
+ // OpenCL stuff
+
+ private IntBuffer errorCode = BufferUtils.createIntBuffer(1);
+
+ private CLDevice clDevice;
+ private CLContext clContext;
+ private CLCommandQueue queue;
+ private CLProgram program;
+ private CLKernel kernel;
+ private CLMem clTransform;
+
+ private PointerBuffer kernelGlobalWorkSize;
+
+ private SpriteShootoutCL() {
+ }
+
+ public static void main(String[] args) {
+ try {
+ new SpriteShootoutCL().start();
+ } catch (LWJGLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void start() throws LWJGLException {
+ try {
+ initGL();
+ initCL();
+
+ renderer = new SpriteRendererDefault();
+
+ updateBalls(ballCount);
+ run();
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ destroy();
+ }
+ }
+
+ private void initCL() throws LWJGLException {
+ CL.create();
+
+ final List<CLPlatform> platforms = CLPlatform.getPlatforms();
+ if ( platforms == null )
+ throw new RuntimeException("No OpenCL platforms found.");
+
+ final CLPlatform platform = platforms.get(0);
+
+ final PointerBuffer ctxProps = BufferUtils.createPointerBuffer(3);
+ ctxProps.put(CL_CONTEXT_PLATFORM).put(platform.getPointer()).put(0).flip();
+
+ // Find devices with GL sharing support
+ final Filter<CLDevice> glSharingFilter = new Filter<CLDevice>() {
+ public boolean accept(final CLDevice device) {
+ final CLDeviceCapabilities caps = CLCapabilities.getDeviceCapabilities(device);
+ return caps.CL_KHR_gl_sharing;
+ }
+ };
+ final List<CLDevice> devices = platform.getDevices(CL_DEVICE_TYPE_GPU, glSharingFilter);
+
+ if ( devices == null )
+ throw new RuntimeException("No OpenCL GPU device found.");
+
+ clDevice = devices.get(0);
+ // Make sure we use only 1 device
+ devices.clear();
+ devices.add(clDevice);
+
+ clContext = CLContext.create(platform, devices, new CLContextCallback() {
+ protected void handleMessage(final String errinfo, final ByteBuffer private_info) {
+ System.out.println("[CONTEXT MESSAGE] " + errinfo);
+ }
+ }, Display.getDrawable(), errorCode);
+ checkCLError(errorCode);
+
+ queue = clCreateCommandQueue(clContext, clDevice, 0, errorCode);
+ checkCLError(errorCode);
+ }
+
+ private void initGL() throws LWJGLException {
+ Display.setLocation((Display.getDisplayMode().getWidth() - SCREEN_WIDTH) / 2,
+ (Display.getDisplayMode().getHeight() - SCREEN_HEIGHT) / 2);
+ Display.setDisplayMode(new DisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT));
+ Display.setTitle("Sprite Shootout - CL");
+ Display.create();
+
+ if ( !GLContext.getCapabilities().OpenGL20 )
+ throw new RuntimeException("OpenGL 2.0 is required for this demo.");
+
+ // Setup viewport
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, SCREEN_WIDTH, 0, SCREEN_HEIGHT, -1.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+
+ // Create textures
+
+ try {
+ texSmallID = createTexture("res/ball_sm.png");
+ texBigID = createTexture("res/ball.png");
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ texID = texBigID;
+
+ // Setup rendering state
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.0f);
+
+ glColorMask(colorMask, colorMask, colorMask, false);
+ glDepthMask(false);
+ glDisable(GL_DEPTH_TEST);
+
+ // Setup geometry
+
+ Util.checkGLError();
+ }
+
+ private static int createTexture(final String path) throws IOException {
+ final BufferedImage img = ImageIO.read(SpriteShootoutCL.class.getClassLoader().getResource(path));
+
+ final int w = img.getWidth();
+ final int h = img.getHeight();
+
+ final ByteBuffer buffer = readImage(img);
+
+ final int texID = glGenTextures();
+
+ glBindTexture(GL_TEXTURE_2D, texID);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
+
+ return texID;
+ }
+
+ private static ByteBuffer readImage(final BufferedImage img) throws IOException {
+ final Raster raster = img.getRaster();
+
+ final int bands = raster.getNumBands();
+
+ final int w = img.getWidth();
+ final int h = img.getHeight();
+
+ final int size = w * h * bands;
+
+ final byte[] pixels = new byte[size];
+ raster.getDataElements(0, 0, w, h, pixels);
+
+ final ByteBuffer pbuffer = BufferUtils.createByteBuffer(size);
+
+ if ( bands == 4 ) {
+ for ( int i = 0; i < (w * h * 4); i += 4 ) {
+ // Pre-multiply alpha
+ final float a = unpackUByte01(pixels[i + 3]);
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 2]) * a));
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 1]) * a));
+ pbuffer.put(packUByte01(unpackUByte01(pixels[i + 0]) * a));
+ pbuffer.put(pixels[i + 3]);
+ }
+ } else if ( bands == 3 ) {
+ for ( int i = 0; i < (w * h * 3); i += 3 ) {
+ pbuffer.put(pixels[i + 2]);
+ pbuffer.put(pixels[i + 1]);
+ pbuffer.put(pixels[i + 0]);
+ }
+ } else
+ pbuffer.put(pixels, 0, size);
+
+ pbuffer.flip();
+
+ return pbuffer;
+ }
+
+ private static float unpackUByte01(final byte x) {
+ return (x & 0xFF) / 255.0f;
+ }
+
+ private static byte packUByte01(final float x) {
+ return (byte)(x * 255.0f);
+ }
+
+ private void updateBalls(final int count) {
+ System.out.println("NUMBER OF BALLS: " + count);
+ renderer.updateBalls(ballCount);
+ }
+
+ private void run() {
+ long startTime = System.currentTimeMillis() + 5000;
+ long fps = 0;
+
+ long time = Sys.getTime();
+ final int ticksPerUpdate = (int)(Sys.getTimerResolution() / ANIMATION_TICKS);
+
+ renderer.render(false, true, 0);
+
+ while ( run ) {
+ Display.processMessages();
+ handleInput();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ final long currTime = Sys.getTime();
+ final int delta = (int)(currTime - time);
+ if ( smooth || delta >= ticksPerUpdate ) {
+ renderer.render(render, animate, delta);
+ time = currTime;
+ } else
+ renderer.render(render, false, 0);
+
+ Display.update(false);
+
+ if ( startTime > System.currentTimeMillis() ) {
+ fps++;
+ } else {
+ long timeUsed = 5000 + (startTime - System.currentTimeMillis());
+ startTime = System.currentTimeMillis() + 5000;
+ System.out.println("FPS: " + (Math.round(fps / (timeUsed / 1000.0) * 10) / 10.0) + ", Balls: " + ballCount);
+ fps = 0;
+ }
+ }
+ }
+
+ private void handleInput() {
+ if ( Display.isCloseRequested() )
+ run = false;
+
+ while ( Keyboard.next() ) {
+ if ( Keyboard.getEventKeyState() )
+ continue;
+
+ switch ( Keyboard.getEventKey() ) {
+ case Keyboard.KEY_1:
+ case Keyboard.KEY_2:
+ case Keyboard.KEY_3:
+ case Keyboard.KEY_4:
+ case Keyboard.KEY_5:
+ case Keyboard.KEY_6:
+ case Keyboard.KEY_7:
+ case Keyboard.KEY_8:
+ case Keyboard.KEY_9:
+ case Keyboard.KEY_0:
+ ballCount = 1 << (Keyboard.getEventKey() - Keyboard.KEY_1);
+ updateBalls(ballCount);
+ break;
+ case Keyboard.KEY_ADD:
+ case Keyboard.KEY_SUBTRACT:
+ int mult;
+ if ( Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT) )
+ mult = 1000;
+ else if ( Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU) )
+ mult = 100;
+ else if ( Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL) )
+ mult = 10;
+ else
+ mult = 1;
+ if ( Keyboard.getEventKey() == Keyboard.KEY_SUBTRACT )
+ mult = -mult;
+ ballCount += mult * 100;
+ if ( ballCount <= 0 )
+ ballCount = 1;
+ updateBalls(ballCount);
+ break;
+ case Keyboard.KEY_ESCAPE:
+ run = false;
+ break;
+ case Keyboard.KEY_A:
+ animate = !animate;
+ System.out.println("Animation is now " + (animate ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_C:
+ colorMask = !colorMask;
+ glColorMask(colorMask, colorMask, colorMask, false);
+ System.out.println("Color mask is now " + (colorMask ? "on" : "off") + ".");
+ // Disable alpha test when color mask is off, else we get no benefit.
+ if ( colorMask ) {
+ glEnable(GL_BLEND);
+ glEnable(GL_ALPHA_TEST);
+ } else {
+ glDisable(GL_BLEND);
+ glDisable(GL_ALPHA_TEST);
+ }
+ break;
+ case Keyboard.KEY_R:
+ render = !render;
+ System.out.println("Rendering is now " + (render ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_S:
+ smooth = !smooth;
+ System.out.println("Smooth animation is now " + (smooth ? "on" : "off") + ".");
+ break;
+ case Keyboard.KEY_T:
+ if ( texID == texBigID ) {
+ texID = texSmallID;
+ ballSize = 16;
+ } else {
+ texID = texBigID;
+ ballSize = 42;
+ }
+ renderer.updateBallSize();
+ glBindTexture(GL_TEXTURE_2D, texID);
+ System.out.println("Now using the " + (texID == texBigID ? "big" : "small") + " texture.");
+ break;
+ case Keyboard.KEY_V:
+ vsync = !vsync;
+ Display.setVSyncEnabled(vsync);
+ System.out.println("VSYNC is now " + (vsync ? "enabled" : "disabled") + ".");
+ break;
+ }
+ }
+
+ while ( Mouse.next() ) ;
+ }
+
+ private static void checkCLError(IntBuffer buffer) {
+ org.lwjgl.opencl.Util.checkCLError(buffer.get(0));
+ }
+
+ private void destroy() {
+ clReleaseContext(clContext);
+ Display.destroy();
+ System.exit(0);
+ }
+
+ private abstract class SpriteRenderer {
+
+ protected int progID;
+ protected int animVBO;
+
+ protected void createKernel(final String source) {
+ program = clCreateProgramWithSource(clContext, source, errorCode);
+ checkCLError(errorCode);
+ final int build = clBuildProgram(program, clDevice, "", null);
+ if ( build != CL_SUCCESS ) {
+ System.out.println("BUILD LOG: " + program.getBuildInfoString(clDevice, CL_PROGRAM_BUILD_LOG));
+ throw new RuntimeException("Failed to build CL program, status: " + build);
+ }
+
+ kernel = clCreateKernel(program, "animate", errorCode);
+ checkCLError(errorCode);
+
+ kernelGlobalWorkSize = BufferUtils.createPointerBuffer(1);
+ kernelGlobalWorkSize.put(0, ballCount);
+
+ kernel.setArg(0, SCREEN_WIDTH);
+ kernel.setArg(1, SCREEN_HEIGHT);
+ kernel.setArg(2, ballSize * 0.5f);
+ }
+
+ protected void createProgram(final int vshID) {
+ final int fshID = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fshID, "#version 110\n" +
+ "uniform sampler2D COLOR_MAP;" +
+ "void main(void) {\n" +
+ " gl_FragColor = texture2D(COLOR_MAP, gl_PointCoord);\n" +
+ "}");
+ glCompileShader(fshID);
+ if ( glGetShader(fshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(fshID, glGetShader(fshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile fragment shader.");
+ }
+
+ progID = glCreateProgram();
+ glAttachShader(progID, vshID);
+ glAttachShader(progID, fshID);
+ glLinkProgram(progID);
+ if ( glGetProgram(progID, GL_LINK_STATUS) == GL_FALSE ) {
+ System.out.println(glGetProgramInfoLog(progID, glGetProgram(progID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to link shader program.");
+ }
+
+ glUseProgram(progID);
+ glUniform1i(glGetUniformLocation(progID, "COLOR_MAP"), 0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ }
+
+ public void updateBallSize() {
+ glPointSize(ballSize);
+ kernel.setArg(2, ballSize * 0.5f);
+ }
+
+ public void updateBalls(final int count) {
+ kernelGlobalWorkSize.put(0, ballCount);
+
+ final FloatBuffer transform = BufferUtils.createFloatBuffer(count * 4);
+
+ final Random random = new Random();
+ for ( int i = 0; i < count; i++ ) {
+ transform.put((int)(random.nextFloat() * (SCREEN_WIDTH - ballSize)) + ballSize * 0.5f);
+ transform.put((int)(random.nextFloat() * (SCREEN_HEIGHT - ballSize)) + ballSize * 0.5f);
+ transform.put(random.nextFloat() * 0.4f - 0.2f);
+ transform.put(random.nextFloat() * 0.4f - 0.2f);
+ }
+ transform.flip();
+
+ if ( animVBO != 0 ) {
+ clReleaseMemObject(clTransform);
+ glDeleteBuffers(animVBO);
+ }
+
+ animVBO = glGenBuffers();
+
+ glBindBuffer(GL_ARRAY_BUFFER, animVBO);
+ glBufferData(GL_ARRAY_BUFFER, transform, GL_STATIC_DRAW);
+ glVertexPointer(2, GL_FLOAT, (4 * 4), 0);
+
+ clTransform = clCreateFromGLBuffer(clContext, CL_MEM_READ_WRITE, animVBO, errorCode);
+ checkCLError(errorCode);
+ kernel.setArg(4, clTransform);
+ }
+
+ protected abstract void render(boolean render, boolean animate, int delta);
+
+ }
+
+ private class SpriteRendererDefault extends SpriteRenderer {
+
+ SpriteRendererDefault() {
+ System.out.println("Shootout Implementation: OpenCL GPU animation");
+
+ final int vshID = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vshID, "#version 150\n" +
+ "void main(void) {\n" +
+ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" +
+ "}");
+ glCompileShader(vshID);
+ if ( glGetShader(vshID, GL_COMPILE_STATUS) == GL_FALSE ) {
+ System.out.println(glGetShaderInfoLog(vshID, glGetShader(vshID, GL_INFO_LOG_LENGTH)));
+ throw new RuntimeException("Failed to compile vertex shader.");
+ }
+
+ createProgram(vshID);
+
+ Util.checkGLError();
+
+ createKernel("kernel void animate(\n" +
+ " const int WIDTH,\n" +
+ " const int HEIGHT,\n" +
+ " const float radius,\n" +
+ " const int delta,\n" +
+ " global float4 *balls\n" +
+ ") {\n" +
+ " unsigned int b = get_global_id(0);\n" +
+ "\n" +
+ " float4 anim = balls[b];\n" +
+ " anim.xy = anim.xy + anim.zw * delta;\n" +
+ " float2 animC = clamp(anim.xy, (float2)radius, (float2)(WIDTH - radius, HEIGHT - radius));\n" +
+ " if ( anim.x != animC.x ) anim.z = -anim.z;\n" +
+ " if ( anim.y != animC.y ) anim.w = -anim.w;\n" +
+ "\n" +
+ " balls[b] = (float4)(animC, anim.zw);\n" +
+ "}");
+
+ updateBallSize();
+ }
+
+ publ...
[truncated message content] |
|
From: <sp...@us...> - 2011-04-02 11:33:08
|
Revision: 3512
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3512&view=rev
Author: spasi
Date: 2011-04-02 11:33:02 +0000 (Sat, 02 Apr 2011)
Log Message:
-----------
Attempt to fix NV compilation issue.
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/DemoFractal.java
trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/Mandelbrot.cl
Modified: trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/DemoFractal.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/DemoFractal.java 2011-03-30 09:35:14 UTC (rev 3511)
+++ trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/DemoFractal.java 2011-04-02 11:33:02 UTC (rev 3512)
@@ -518,12 +518,9 @@
glDeleteBuffers(glIDs);
}
- if ( useTextures )
+ if ( useTextures ) {
glGenTextures(glIDs);
- else
- glGenBuffers(glIDs);
- if ( useTextures ) {
// Init textures
for ( int i = 0; i < slices; i++ ) {
glBindTexture(GL_TEXTURE_2D, glIDs.get(i));
@@ -535,6 +532,8 @@
}
glBindTexture(GL_TEXTURE_2D, 0);
} else {
+ glGenBuffers(glIDs);
+
// setup one empty PBO per slice
for ( int i = 0; i < slices; i++ ) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glIDs.get(i));
Modified: trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/Mandelbrot.cl
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/Mandelbrot.cl 2011-03-30 09:35:14 UTC (rev 3511)
+++ trunk/LWJGL/src/java/org/lwjgl/test/opencl/gl/Mandelbrot.cl 2011-04-02 11:33:02 UTC (rev 3512)
@@ -57,7 +57,7 @@
output[iy * width + ix] = 0;
#endif
} else {
- varfloat alpha = (varfloat)iteration / maxIterations;
+ float alpha = (float)iteration / maxIterations;
int colorIndex = (int)(alpha * colorMapSize);
#ifdef USE_TEXTURE
// We could have changed colorMap to a texture + sampler, but the
@@ -69,9 +69,9 @@
(c & 0xFF) >> 0,
(c & 0xFF00) >> 8,
(c & 0xFF0000) >> 16,
- _255
+ 255.0f
);
- write_imagef(output, (int2)(ix, iy), oc / _255);
+ write_imagef(output, (int2)(ix, iy), oc / 255.0f);
#else
output[iy * width + ix] = colorMap[colorIndex];
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|