Eigene Renderengine ohne Java3D,etc.

Matyr

Mitglied
Hi,
ich habe vor (nicht ganz freiwillig) eine komplett eigene Render-Engine in java zu bauen.
Diese soll (leider) nur mit Standert JDK Inhalte funktionieren.
Dabei zu sagen ist das ich relativ neu in Java bin, aber einige Jahre C++ Erfahrung habe.

Die Grundlagen stehen schon, aber aktuell bricht mir leider die Performance massiv ein.

Grundlegender Aufbau des Renderns:

- Sortiere eine Liste aller Objekte anhand der z (Entfernung) Koordinaten.
- Nun transformier Objekt-Space in World-Space
- Bilde das Objekt mit Perspektivischer Transformation auf die X-Y (Bildschirm) ebene ab
- Textur (die im RAM liegt) transformieren und auf ein Img "rendern" das hinterher angezeigt wird

Zeichnen von Quadratischen "einfachen" Objekten läuft über Graphics2D.draw,
das Transformierte zeichnen läuft über Pixelarrays (DataBufferInt).

Image Typ ist aktuell BufferedImage, alles läuft in einem Thread.

Der größte Geschwindigkeits verlust entsteht beim Zeichnen von Objekten (unteranderem weil Clipping fehlt)

Falls irgendjemand Tipps kennt wie man alles optiemieren kann würde ich mich freuen davon zu hören.

Einige Source Code beispiele:


Alle Objekte zeichnen und das fertige img zurückgeben, mit Caching wenn nichts geändert wurde.
BitmapBit arbeitet auf Pixelarrays
Java:
public BitmapJ2D tick(long frameCount)
	{		
				
		boolean up = false;
		frame.draw(old, 0, 0);
		frame.fill(0xff000000);
		
		BitmapBit BBit = null;
		
		java.util.Collections.sort(objects);			
			
		for(EntityBase itr : objects)
		{		
			itr.addAng(new Vector3(0,0.01,0));
			Vector3[] tmp = itr.toWorld();
			
			if(itr instanceof Plane)
			{
				//if(itr.getUpdate())
				{			
					if(BBit==null){BBit = new BitmapBit(WIDTH,HEIGHT,((DataBufferInt)((BufferedImage)frame.getImg()).getRaster().getDataBuffer()).getData());}
					
					for(int i=0;i<4;i++) { this.Project(tmp[i]);}				
				
					//System.out.println(tmp[0].toString()+ tmp[1].toString() + tmp[2].toString() + tmp[3].toString());
					//Transform draw 					
					BBit.drawTransform(((Plane)itr).getTopTexture(),tmp[0], tmp[1], tmp[2], tmp[3]);
					itr.cache(tmp);
					itr.setUpdate(false);
					up=true;
				}				
			}
		}
		if(up)
		{
			old.fill(0xff000000);
			old.draw(frame,0,0);
			up = false;
		}
		return frame;
	}

Falls weitere source Inhalte gebraucht werden bitte melden, ich wollt nicht alles vollposten...
 

Landei

Top Contributor
Nur mit Java-Bordmitteln (also Java2D) ist harsch. Das wird nur für kleine Szenen klappen, ansonsten brauchst du irgendwie einen möglichst direkten Zugang zu OpenGL oder DirectX.
 

Matyr

Mitglied
Stimmt viele, Objekte parallel zeichnen geht nicht, aber durch einen Cache und begrentztem neuzeichnen von veränderten Objekten kann man was machen.

Ich habe heute was von VolatileImage gelesen lohnt es sich diese zu benutzen?
 

Landei

Top Contributor
Soweit ich weiß kann das viel bringen, ist aber schweine-kompliziert, weil es eben jederzeit wieder freigegeben werden kann.
 

Matyr

Mitglied
Würde man dann alles ersetzen, also auch die Images die nur gelesen werden (texturen aus dateien),

oder nur das eine Image auf das geschrieben wird?

Mfg. Matyr
 

Cola_Colin

Top Contributor
VolatileImage kann sehr sehr viel bringen, ist auch nur beim "malen" des Bildes wichtig, d.h. die Texturen können BufferedImage sein, das Lesen ist da trotzdem schon beschleunigt, schreiben hingegen läuft auf einem VolatileImage massiv schneller, wenn es den unterstützt wird.

Siehe http://java.sun.com/j2se/1.4/pdf/VolatileImage.pdf

So schwer ist das imho auch gar nicht zu nutzen.
 

Matyr

Mitglied
1)
Kann ich irgendwie auf das Pixel Array in VolatileImage zugreifen?

Ich muss für das Perspektivische Zeichnen ziemlich unregelmäßige Figuren in das Image bekommen, aktuell läuft das über ein BufferedImage und kopiert dies in das Volatile hinein.


2)
Ich suche auch noch nach einen schnellen Alghoritmus für die Texture-transformation ( Mapping) um die Rechteckigen Texturen auf die Figuren zu bekommen, kennt irgendwer einen?
 

Matyr

Mitglied
Drei weitere sachen, ich hab jetzt alles auf VolatileImage geändert, aber die Funktion
Java:
public void draw()
	{
		
		BufferStrategy bs = getBufferStrategy();
		if (bs == null) {
			createBufferStrategy(2);
			return;
		}		
		
		Graphics g = bs.getDrawGraphics();	
		Graphics2D g2 = (Graphics2D)g;
		
		g2.drawImage(screen.getImg(),0,0,getWidth(),getHeight(),null);
		g2.dispose();
		bs.show();
	}

ist irgendwie seeeeehr langsam, sobald ich drawImage auskommentiere habe ich einen Geschwindigkeits gewinn von 4 auf >100fps.
Weiß einer was da falsch laufen kann? Da das Image mit
Java:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
		GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
		VolatileImage image = null;

		image = gc.createCompatibleVolatileImage(width, height, transparency);

erzeug ist sollte es ja eigentlich keine Probleme geben.

2) Ich male aktuell in ein Canvas, das sollte von der geschwindigkeit im normallen bereich liegen, oder gibt es etwas drastisch schnelleres? Ich nutze keine repaint sondern einfach ein endlos loop der immer neu zeichnet.

3) Ist es effetkiver nicht immer image objekte zu übergeben sonder Graphics2D objecte?

Mfg. Matyr
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Hab' nicht alles verfolgt, aber
Code:
g2.drawImage(screen.getImg(),0,0,getWidth(),getHeight(),null);
Ist das 'Img' dort genau getWidth*getHeight groß? Wenn nicht, wird es bei jedem Zeichnen skaliert. Ändere das mal zu
Code:
g2.drawImage(screen.getImg(),0,0,null);
und passe stattdessen falls nötig die Größe von "Img" an.
 

Matyr

Mitglied
Ok, das war das Problem auch wenn ich nicht verstehe wieso das vergrößern so eine laufzeit hat.Danke

Trotzdem habe ich noch mit BufferedImage eine bessere laufzeit als mit VolatileImage
 
Zuletzt bearbeitet:

EgonOlsen

Bekanntes Mitglied
Nur mit Java-Bordmitteln (also Java2D) ist harsch. Das wird nur für kleine Szenen klappen, ansonsten brauchst du irgendwie einen möglichst direkten Zugang zu OpenGL oder DirectX.
Ich verstehe jetzt nicht so ganz, wie die Texturen hier gerendert werden (es wäre schön, wenn man das Ding mal als Ganzes zum selber ausführen sehen könnte), aber du kannst mit Software-Rendering in Java schon einiges machen. Du musst dich nur von dem ganzen Java2D-Geraffel verabschieden und die Pixel "von Hand" in ein BufferedImage malen. Ein kleines Beispiel dazu als Applet: http://www.jpct.net/quapplet/
 

twseitex

Mitglied
Hi,

ein Gegenbeispiel: Mein Java-Audioplayer ht eine GUI, die
die Fensterstruktur und Elemente als variable Bausteine nutzt. Also eine
Fensterklasse und deren Elemente. Es können mehrere Fenster - eigentlich
beliebig viele - gerendert werden. Alle Fensterlemente wie Buttons sind
optional, z.T. animiert (eigene Threads) und im Container gekapselt
und werden dynamisch erzeugt (daher optional). Graphic2D ist parallel
implementiert. Aduio sowieso parallel. Alles wird von einer anderen
Klasse synchronisert. Also 3 parallele Renderaktionen mit Synchron
(1x Audio, 1x Fenster, 1x Graphic2D in einem Fensterlemenent).

War eine Schweine Arbeit, läuft, aber Java frisst Ressourcen endlos.
Ich würde es nie wieder machen, das zu programmieren.

Mit anderen Worten: Überzeuge denjenigen, der die Rendermaschine in
Java verlangt, Fertiges zu verwenden, das optimiert ist. Java3D ist leider
uralt. Und möglichst nur hoch optimierte Fertigbausteine, wenn
mit Bytecode realisiert.


Mit createVolatileImage() habe ich folgende reizende Erfahrung gemacht:

#
# An unexpected error has been detected by Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x02e7920c,
pid=3584, tid=3492
#
# Java VM: Java HotSpot(TM) Client VM (11.3-b02 mixed mode,
sharing windows-x86)
# Problematic frame:
# C [awt.dll+0x3920c]
#
# If you would like to submit a bug report, please visit:
# HotSpot Virtual Machine Error Reporting Page
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
*/
 

Matyr

Mitglied
Selber ausführen wird aktuell schwierig. Ich hab aktuell aufgrund der Laufzeit auf isometrische Perspektive gesetzt, daher keine Drehung in die Tiefe.

Intern werkelt noch an allem die selbe engine.

Texturen werden wie folgt gezeichnet: es werden alle Pixel der Textur Datei durchlaufen und mit entsprechenden Matrix Operationen auf den Monitor projiziert. Wenn die Textur zu groß ist gibt es massive Performance Einbrüche, wenn sie zu klein ist löcher auf dem Objekt, daher nicht gerade ideal.

Aber wie gesagt ich werde wahrscheinlich jetzt isometrische Perspektive nehmen
 

0x7F800000

Top Contributor
1) Wieso wird irgendwas nach der Tiefe sortiert? GraKa's verwenden Z-Stencil-Buffer, und arbeiten auf Pixel-Ebene. Ansonsten kannst du nicht mal zwei sich schneidende Dreiecke malen
2) Java2D-Kram ist wohl nicht nötig, wenn du eh alles selbst zeichnest: mal also alles direkt in ein int-array rein
3) Bei jedem halbwegs sinnvoll implementierten Programm dieser Art dürfte es keinerlei Unterschiede zwischen der isometrischen Perspektive und der normalen Perspektive geben: dafür muss doch nur ein einzelner eintrag in der Projektionsmatrix geflippt werden
4) Texturen werden nicht aus Dateien gezeichnet. Wenn du das schon nicht alles auf der grafikkarte ausführst, dann müssen die Texturen wenigstens im Speicher liegen.
5) es wird nicht von der Textur auf Bildschirm sondern vom Bildschirm auf die Textur gemappt, mit der inversen Homographie und zusätzlich einem bilinearen filter & MIP-Maps.
 
Zuletzt bearbeitet:

Matyr

Mitglied
- Java2D kram ist meiner ansicht nach deutlich schneller als das beschreiben eines int-Arrays.
(Meines wissens sollte das ja direkt optimiert als maschinencode vorliegen)

- Nach tiefe sortieren tue ich, weil dies für meine problemstellung ausreicht und deutlich weniger performance zieht als aufwendige methoden ( und ich mich ehrlich gesagt nicht gut mit solchen clipping alghoritmen auskenne)

- Den begriff inverse Homographie habe ich bis jetzt noch nicht gehört werde aber mal suchen ob ich was entsprechendes finde.

- Meine Texturen liegen im RAM, wahrscheinlich habe ich micht dabei nicht klar genug ausgedrückt.
 

0x7F800000

Top Contributor
- Java2D kram ist meiner ansicht nach deutlich schneller als das beschreiben eines int-Arrays.
Okay... kommt darauf an, was du davon benutzst, und wie du es benutzst

Wenn du irgendetwas pixel-für-pixel zeichnest, dann passiert das ganze nicht auf der graka, sondern im normalen ram, mit normalen Prozessor. Da macht es wenig sinn, durch drei wrapper-ebenen hindurch die gleichen einträge eines stinknormalen arrays anzusprechen.

- Den begriff inverse Homographie habe ich bis jetzt noch nicht gehört werde aber mal suchen ob ich was entsprechendes finde.
Naja, die perspektivische Verzerrung einer Textur bildet geraden auf geraden ab, ist also eine Homographie, und kann dementsprechend durch eine 3x3-Matrix dargestellt werden. Diese kann man invertieren, um von Bildschirmkoordinaten zu Texturkoordinaten zu kommen. Dann läuft man alle Pixel durch, findet ihre textur-Koordinaten mithilfe der inversen Matrix raus, und liest die Farbe der Textur an dieser Stelle ab, beispielsweise mithilfe der bilinearen Interpolation.

- Meine Texturen liegen im RAM, wahrscheinlich habe ich micht dabei nicht klar genug ausgedrückt.
Okay, das war voll korinthenkackig, sorry :oops:
 

EgonOlsen

Bekanntes Mitglied
Naja, die perspektivische Verzerrung einer Textur bildet geraden auf geraden ab, ist also eine Homographie, und kann dementsprechend durch eine 3x3-Matrix dargestellt werden. Diese kann man invertieren, um von Bildschirmkoordinaten zu Texturkoordinaten zu kommen. Dann läuft man alle Pixel durch, findet ihre textur-Koordinaten mithilfe der inversen Matrix raus, und liest die Farbe der Textur an dieser Stelle ab, beispielsweise mithilfe der bilinearen Interpolation.
Ja, kann man so machen...muss man aber zu Glück nicht, denn es wird viel zu langsam für jedes Pixel mit einer Matrix rumzufummeln. Man braucht keine Matrizen an dieser Stelle. Mit den Texturkoordinaten u/v und der Tiefe z an den Eckpunkten eines Dreiecks hat man alles, was man für perspektivisch korrekte Texturen braucht. Ich habe das vor Jahren mal kurz in diesem Thread beschrieben: http://www.java-forum.org/softwareentwicklung/14211-funktioniert-eigentlich-texture-mapping.html#post88556
 

0x7F800000

Top Contributor
Wieder was dazugelernt... Okay, aus performancegründen schreibt man das nicht als matrix hin, sondern ein wenig "direkter", samt den ganzen Bruchstrichen, und macht es nicht für alle Pixel, sondern für wenige punkte, die über das dreieck verstreut sind: gut. Mir ging es eigentlich weniger um Matrizen, sondern um die Richtung Bild -> Textur, statt andersherum.
 

Matyr

Mitglied
Ok, ich guck mir das ganze mal an und probier dann mal drauf los :)


Okay... kommt darauf an, was du davon benutzst, und wie du es benutzst

Wenn du irgendetwas pixel-für-pixel zeichnest, dann passiert das ganze nicht auf der graka, sondern im normalen ram, mit normalen Prozessor. Da macht es wenig sinn, durch drei wrapper-ebenen hindurch die gleichen einträge eines stinknormalen arrays anzusprechen.

Zum malen der Hintergrundbilder und Interfaces/Menüs benutze ich vorallem Java2D, aufgrund der großen fläche (Vollbild) ist dies schneller als wenn ich ein Array mit z.B. 1680*1050 Elementen durchlaufe und für jeden Pixel eine Funktion aufrufe die die Farbe richtig berechnet (aufgrund von RGBA).
 

0x7F800000

Top Contributor
Nja, man muss ja die 3D-Grafik nicht sofort in dasselbe Bild wie die ganzen restlichen knöpfe reinquetschen, man kann's vielleicht auch erstmal auf einem separaten bild mit transparenten Hintergrund malen, und dann zum rest hinzufügen... Wobei ich ehrlich gesagt keine Ahnung habe, wozu du das ganze eigentlich machst, ich kenne 3D-Grafik eigentlich nur von 3D-Spielen und komplizierten Funktionsplottern: nichts davon enthält normalerweise irgendwelche Swing-Knöpfe in der selben komponente. Da ich das Ziel nicht kenne, halte ich mich ab jetzt ein wenig zurück. :)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
C Eigene Minecraft Enchantements Spiele- und Multimedia-Programmierung 1
C Eine eigene 3d Engine : Shader - aber wie ? Spiele- und Multimedia-Programmierung 2
S Eigene Klasse vec_t - 3 oder 4 Einheiten für x, y, z und w Spiele- und Multimedia-Programmierung 11
J Minecraft Eigene Buttons "bauen" á la MineCraft Spiele- und Multimedia-Programmierung 11
N Eigene Java 3D Engine erstellen. Spiele- und Multimedia-Programmierung 11
D JOGL2 eigene mipmaps laden Spiele- und Multimedia-Programmierung 13
Steev Eigene Repaint-Logik Spiele- und Multimedia-Programmierung 17
P eigene Konsole Spiele- und Multimedia-Programmierung 6
M Eigene Strings zeichnen Spiele- und Multimedia-Programmierung 4
N RotationInterpolator um die eigene X-Achse Spiele- und Multimedia-Programmierung 2
M um eigene Achse drehen Spiele- und Multimedia-Programmierung 3
R Eigene geometrische Formen Spiele- und Multimedia-Programmierung 2
E Programmierung eines 2.5D Point&Click Adventures ohne Spieleengine machbar? Spiele- und Multimedia-Programmierung 14
J Bild ohne Quallitätsverlust skalieren Spiele- und Multimedia-Programmierung 11
E Rotation um Bildmittelpunkt ohne Affine Transform!!!!! Spiele- und Multimedia-Programmierung 13
A 2D Spiel ohne Tiles Spiele- und Multimedia-Programmierung 10
S Mausklicks innerhalb eines JFrames/SWTBrowser ohne richtige Maus simulieren Spiele- und Multimedia-Programmierung 6
B Bild ohne Image auf die Festplatte streamen Spiele- und Multimedia-Programmierung 4
Devil0s 2D Stadt Generator/2D Welt speichern OHNE Tiles Spiele- und Multimedia-Programmierung 5
H zwei ints als key in map (ohne long) Spiele- und Multimedia-Programmierung 16
M Multiplayer Game mit Frontend auf HTML5 - ohne ständigen Client Request - Möglich?! Spiele- und Multimedia-Programmierung 12
S Sounds abspielen, ohne sie jedesmal neu zu laden Spiele- und Multimedia-Programmierung 8
B Bilder in GUI ändern ohne repaint() Spiele- und Multimedia-Programmierung 6
C java 3d ohne Java3d Spiele- und Multimedia-Programmierung 28
H Skalierung eines Polygons ohne das es verschoben wird Spiele- und Multimedia-Programmierung 3
K Java3D als Applet ohne Installation von Java3d Spiele- und Multimedia-Programmierung 6
M Aktien-Spiel ohne GUI Spiele- und Multimedia-Programmierung 28
aze Java3D: Gegenstände aufeinander zubewegen ohne Kollision Spiele- und Multimedia-Programmierung 4
A JMF ohne Installation Spiele- und Multimedia-Programmierung 4
Developer_X Sound Lautstärke ohne spezifische API regulieren Spiele- und Multimedia-Programmierung 3
L JMF Player spielt mp3 nur ohne Ton Spiele- und Multimedia-Programmierung 14
M Binärbaum ohne Überlappung zeichnen Spiele- und Multimedia-Programmierung 3
T 3D-Tetris Feld neuzeichnen ohne neue Branchgroup Spiele- und Multimedia-Programmierung 18
O Java3D-Applet ohne Java3D-Runtime ausführen Spiele- und Multimedia-Programmierung 2
L klick auf ComboBox ohne ActionListener --> CPU ausgelaste Spiele- und Multimedia-Programmierung 13
H Tic Tac Toe / 3 Gewinnt OHNE Applet Spiele- und Multimedia-Programmierung 9
S 3D Objekte ohne Java3D darstellen? Spiele- und Multimedia-Programmierung 10
B Sudoku Generator ohne Solerver möglich? Spiele- und Multimedia-Programmierung 20
G Farbig zeichnen ohne java.awt.Color? Spiele- und Multimedia-Programmierung 5

Ähnliche Java Themen

Neue Themen


Oben