OpenGL Skalowanie tekstur

OpenGL Skalowanie tekstur
M9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 8 lat
  • Postów:31
0

Witam, od wczoraj zacząłem moją zabawę z opengl i mam pewien problem. Otóż napisałem metodę która ułatwia rysowanie obrazów podczas ustawiania wielkości zwykłego obrazu nie ma żadnego problemu, lecz przy próbie rysowania obrazu z kanałem alpha obraz jest mniejszy niż powinien.
Dla rozjaśnienia sytuacji podam dwa zdjęcia
<image>9d8dec49ac.png</image>
Rycerz po lewej teoretycznie jest takiej samej wielkości jak zielony kwadrat.
<image>e4c9206c38.png</image>
Na drugim zdjęciu widać to dokładnie. Nie wiem w czym leży problem, zwykłym obrazom można ustawić wielkość bez problemu lecz tym z kanałem alpha już nie.
Będę wdzięczny za pomoc.

Kopiuj
 

public static void DrawImage(Texture texture,int x,int y, int width, int height){
		if(texture != null){
			texture.bind();
			glEnable(GL_BLEND);
			glBlendFunc(GL_ONE, GL_ZERO);
			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	
			//set transparency
			glColor4f(1, 1, 1,1);
			//
			glTranslatef(x, y, 0);
			glBegin(GL_QUADS);
			glTexCoord2f(0, 0);
			glVertex2i(0, 0);
			glTexCoord2f(1, 0);
			glVertex2i(width, 0);
			glTexCoord2f(1, 1);
			glVertex2i(width, height);
			glTexCoord2f(0, 1);
			glVertex2i(0, height);
			glEnd();
			glLoadIdentity(); 
			
			
		}
	} 
Kopiuj
 
        Texture tex = LoadTexture("res/1.png", "PNG");
        Texture t2 = LoadTexture("res/image.png", "PNG");
     
        while (!Display.isCloseRequested()) {
            int delta = getDelta();
        	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    		
            update(delta);
            renderGL();

        	 DrawImage(tex, 0, 0, 100 , 120);
        	 DrawImage(t2, 100, 0, 100, 120);
             
            Display.update();
            Display.sync(60); // cap fps to 60fps
        } 
edytowany 2x, ostatnio: Marcin902
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:28 minut
  • Postów:6651
0

Ja zawsze wywoływałem TexParameter podczas ładowania tekstury:

Kopiuj
void Texture::Load(string filename,bool fixEdge)
{
	//load and decode
	std::vector<unsigned char> buffer, image;
	loadFile(buffer, filename);
	unsigned long w, h;
	int error = decodePNG(image, w, h, buffer.empty() ? 0 : &buffer[0], (unsigned long)buffer.size());

	if (!error) {
		glEnable(GL_TEXTURE_2D);
		width=w;
		height=h;
		glPixelStorei(GL_UNPACK_ALIGNMENT,4);
		glGenTextures(1,&texID);
		glBindTexture(GL_TEXTURE_2D,texID);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		if (fixEdge) {
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE  );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE  );
		} else {
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT  );
			glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT  );
		}

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]);
	} else {
		cout << "Error: " << filename << endl;
	}
}

CLAMP_TO_EDGE to ważny parametr dla sprite, bo przy nakładaniu tekstury na quada eliminujesz niedoskonałość liczb zmiennoprzecinkowych i nie będą dodawać się śmieci po bokach obrazka ;)

glBlendFunc poprawnie wykorzystujący kanał alpha robiłem zawsze w taki sposób:

Kopiuj
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Nie wiem, czemu dwa razy wywołujesz blend func, z różnymi parametrami.

BTW. przywitaj się z OpenGL 4, albo chociaż 3 ;)


🕹️⌨️🖥️🖱️🎮
edytowany 8x, ostatnio: Spine
M9
Fakt, rzeczywiście powinienem najpierw więcej poczytać, zajmuje się opengl dopiero od wczoraj. Używam lwjgl 2.9.3 i u mnie nie ma takiego parametru CLAMP_TO_EDGE. I nie rozumiem metody decodePNG, na czym ona polega?
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:28 minut
  • Postów:6651
0

Odpowiadaj w wątku, a nie w komentarzach.

decodePNG to funkcja, której używałem w C++ (z "modułu" picopng - http://lodev.org/lodepng/picopng.cpp). To mało istotne w naszych rozważaniach ;)

Na Twoje szczęście lwjgl też używałem ze starym OpenGL. Żeby mieć CLAMP_TO_EDGE prawdopodobnie musisz zaimportować odpowiednie moduły, ja mam taką formułkę w pliku z loaderem tekstur:

Kopiuj
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.PixelFormat.*;
import static org.lwjgl.util.glu.GLU.*;

Do ładowania PNG używałem takich modułów:

Kopiuj
import de.matthiasmann.twl.utils.PNGDecoder;
import de.matthiasmann.twl.utils.PNGDecoder.Format;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.file.Paths;

Tak wygląda moja metoda ładująca PNG w Javie:

Kopiuj
	public void load(String fileName,boolean fixEdge) throws IOException
	{
		InputStream in = null;
		try {
			in = new FileInputStream(Paths.get(fileName).toString());
			PNGDecoder decoder = new PNGDecoder(in);
 
			width=decoder.getWidth();
			height=decoder.getHeight();
			ByteBuffer buf = ByteBuffer.allocateDirect(4*width*height);
			decoder.decode(buf, width*4, Format.RGBA);
			buf.flip();
			texID=glGenTextures();
			glBindTexture(GL_TEXTURE_2D, texID);
 
			// All RGB bytes are aligned to each other and each component is 1 byte
			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
 
			if (fixEdge) {
				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE  );
				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE  );
			} else {
				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT  );
				glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT  );
			}
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
 
			in.close(); // przy 250 uruchomieniach w jednej instancji, krzyczalo, ze za duzo otwartych plikow
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

🕹️⌨️🖥️🖱️🎮
edytowany 3x, ostatnio: Spine
M9
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 8 lat
  • Postów:31
0

@Spine Dodałem ale to nadal nie rozwiązuje problemu, podam kod całej klasy.

Kopiuj
 @SuppressWarnings("unused")
public class Start {
	
	
	
	
	  float x = 400, y = 300;
    float rotation = 0;
  
    /** time at last frame */
    long lastFrame;
  
    /** frames per second */
    int fps;
    /** last fps time */
    long lastFPS;
     
    /** is VSync Enabled */
    boolean vsync;
  
    public void start() {
        try {
            Display.setDisplayMode(new DisplayMode(1280, 720));
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            System.exit(0);
        }
  
    	glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0, 1280, 720, 0, 1, -1);
		glMatrixMode(GL_MODELVIEW);
		glEnable(GL_TEXTURE_2D);
		
        getDelta(); // call once before loop to initialise lastFrame
        lastFPS = getTime(); // call before loop to initialise fps timer
        Texture tex = LoadTexture("res/1.png", "PNG");
        Texture t2 = LoadTexture("res/image.png", "PNG");
        Texture t3 = LoadTexture("res/atack1/1.png", "PNG");
        
        while (!Display.isCloseRequested()) {
            int delta = getDelta();
        	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    		
            update(delta);
          
            	DrawImage(t2, 0, 0, 600, 420);
             	DrawImage(t3, 0, 0, 307, 160);
                
             Display.update();
            Display.sync(60); // cap fps to 60fps
        }
  
        Display.destroy();
        System.exit(0);
    }
  
    public void update(int delta) {
        // rotate quad
        rotation += 0.15f * delta;
  
        if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) x -= 0.35f * delta;
        if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) x += 0.35f * delta;
  
        if (Keyboard.isKeyDown(Keyboard.KEY_UP)) y -= 0.35f * delta;
        if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) y += 0.35f * delta;
  
        while (Keyboard.next()) {
            if (Keyboard.getEventKeyState()) {
                if (Keyboard.getEventKey() == Keyboard.KEY_F) {
                    setDisplayMode(1280, 720, !Display.isFullscreen());
                }
                else if (Keyboard.getEventKey() == Keyboard.KEY_V) {
                    vsync = !vsync;
                    Display.setVSyncEnabled(vsync);
                }
            }
        }
         
        // keep quad on the screen
        if (x < 0) x = 0;
        if (x > 800) x = 800;
        if (y < 0) y = 0;
        if (y > 600) y = 600;
  
        updateFPS(); // update FPS Counter
    }
  
    /**
     * Set the display mode to be used 
     * 
     * @param width The width of the display required
     * @param height The height of the display required
     * @param fullscreen True if we want fullscreen mode
     */
    public void setDisplayMode(int width, int height, boolean fullscreen) {
 
        // return if requested DisplayMode is already set
                if ((Display.getDisplayMode().getWidth() == width) && 
            (Display.getDisplayMode().getHeight() == height) && 
            (Display.isFullscreen() == fullscreen)) {
            return;
        }
         
        try {
            DisplayMode targetDisplayMode = null;
             
            if (fullscreen) {
                DisplayMode[] modes = Display.getAvailableDisplayModes();
                int freq = 0;
                 
                for (int i=0;i<modes.length;i++) {
                    DisplayMode current = modes[i];
                     
                    if ((current.getWidth() == width) && (current.getHeight() == height)) {
                        if ((targetDisplayMode == null) || (current.getFrequency() >= freq)) {
                            if ((targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel())) {
                                targetDisplayMode = current;
                                freq = targetDisplayMode.getFrequency();
                            }
                        }
 
                        // if we've found a match for bpp and frequence against the 
                        // original display mode then it's probably best to go for this one
                        // since it's most likely compatible with the monitor
                        if ((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel()) &&
                            (current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())) {
                            targetDisplayMode = current;
                            break;
                        }
                    }
                }
            } else {
                targetDisplayMode = new DisplayMode(width,height);
            }
             
            if (targetDisplayMode == null) {
                System.out.println("Failed to find value mode: "+width+"x"+height+" fs="+fullscreen);
                return;
            }
 
            Display.setDisplayMode(targetDisplayMode);
            Display.setFullscreen(fullscreen);
             
        } catch (LWJGLException e) {
            System.out.println("Unable to setup mode "+width+"x"+height+" fullscreen="+fullscreen + e);
        }
    }
     
    /** 
     * Calculate how many milliseconds have passed 
     * since last frame.
     * 
     * @return milliseconds passed since last frame 
     */
    public int getDelta() {
        long time = getTime();
        int delta = (int) (time - lastFrame);
        lastFrame = time;
  
        return delta;
    }
  
    /**
     * Get the accurate system time
     * 
     * @return The system time in milliseconds
     */
    public long getTime() {
        return (Sys.getTime() * 1000) / Sys.getTimerResolution();
    }
  
    /**
     * Calculate the FPS and set it in the title bar
     */
    public void updateFPS() {
        if (getTime() - lastFPS > 1000) {
            Display.setTitle("FPS: " + fps);
            fps = 0;
            lastFPS += 1000;
        }
        fps++;
    }
  
    public void initGL() {
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, 800, 0, 600, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
    }
	 
    
    public static void main(String[] argv) {
        Start fullscreenExample = new Start();
        fullscreenExample.start();
        
    }
	
     public static void DrawImage(Texture texture,float x,float y, float width, float height){
		if(texture != null){
			texture.bind();
			
			glEnable(GL_BLEND);
			
			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT  );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT  );
	
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE  );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE  );
   
         
	
			//set transparency
			glColor4f(1, 1, 1,1);
			//
			glTranslatef(x, y, 0);
			glBegin(GL_QUADS);
			glTexCoord2f(0, 0);
			glVertex2f(0, 0);
			glTexCoord2f(1, 0);
			glVertex2f(width, 0);
			glTexCoord2f(1, 1);
			glVertex2f(width, height);
			glTexCoord2f(0, 1);
			glVertex2f(0, height);
			glEnd();
			glLoadIdentity(); 
			
			
		}
	}
	
	
     public static Texture LoadTexture(String path,String fileType){
 		Texture tex = null;
 		InputStream in = ResourceLoader.getResourceAsStream(path);
 		try {
 			tex = TextureLoader.getTexture(fileType, in);
 		} catch (IOException e) {
 			// TODO Auto-generated catch block
 			e.printStackTrace();
 		}
 		return tex;
 		
 	}
	
	
	
	
	
	
	
	
	
}
Spine
  • Rejestracja:około 22 lata
  • Ostatnio:28 minut
  • Postów:6651
0

Powinno być:

Kopiuj
GL12.GL_CLAMP_TO_EDGE

Ale import to załatwia, żeby nie trzeba było pisać nazwy modułu:

Kopiuj
import static org.lwjgl.opengl.GL12.*;

Poza tym jak podajesz kod "całej klasy", to nie obcinaj importów ;)


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)